数据类型是可能值和相关操作的集合。在 Python 中,数据以对象的形式出现,数据类型也即对象类型。
Python 内置了多种数据类型,最常使用的有数字(包括整数 int、浮点数 float、复数 complex,等)、字符串 str、布尔 bool、列表 list、元组 tuple、字典 dict 和 集合 set。
在 Python 中,当您为变量赋值时,会同时根据所赋值的类型设置变量的数据类型。
本章仅介绍 Python 的基本数据类型,即数字、字符串和布尔类型。
数字类型#
数字可以用于表示我们班级的总人数,你的考试成绩,你的身高和体重,你一个月的花销,以及其他任何数量值。
存在三种不同的数字类型:整数、浮点数和复数。此外,布尔类型属于整数的子类型。标准库包含附加的数字类型,如表示有理数的分数类型 fractions.Fraction,以及以用户定制精度表示浮点数的小数类型 decimal.Decimal。
数字是由数字字面值或内置函数与运算符的结果来创建的。Python 完全支持混合运算:当一个二元算术运算符的操作数有不同数值类型时,“较窄”类型的操作数会拓宽到另一个操作数的类型,其中整数比浮点数窄,浮点数比复数窄。
字面量(literal)是用于表达源代码中一个固定值的表示法。下表给出了各种数字字面量的表示示例:
| 字面量 | 解释 |
|---|---|
44, 0, -45, 3141592653589793115997963468 |
整数(大小无限制) |
1.33, 1., 3.14e-10, 3E210, 4.0e+210 |
浮点数 |
0x2c, 0X2C |
十六进制整数 |
0o54, 0O54 |
八进制整数 |
0b101100, 0B101100 |
二进制整数 |
3+4j, 3.0+4.0j, 4J |
复数 |
Decimal('3.1415926535'), Fraction(1, 3) |
小数和分数扩展类型 |
构造函数 int()、float() 和 complex() 也可以用来构造特定类型的数字。
整数是没有小数部分的数值。整数包括正整数、负整数和 0。Python 中的整数可表示的大小没有限制,当数值很大时,会自动转用更高精度存储和计算。以下各变量均为整数类型变量:
import math
a = 33
b = 0
c = -22
d = 2 ** 8
e = a * c
f = int("886")
g = abs(c)
h = math.ceil(3.3)
注意:除了 0 之外,其他整数在表示时不能以 0 开头,如 033 是不可以的。
默认使用十进制表示整数,但也可以使用二进制、八进制和十六进制表示整数。如下所示:
n = 44
n_2 = 0b101100
n_8 = 0o54
n_16 = 0x2c
# 将打印 True True True
print(n == n_2, n == n_8, n == n_16)
# 将打印 44 0b101100 0o54 0x2c
print(n, bin(n), oct(n), hex(n))
虽然在编程时可以用各种进制表示整数,但他们在计算机中的表示却是类似的(即都以二进制表示),因此示例中以各种进制给出的整数值都是相等的。内置函数 bin()、oct() 和 hex() 可以把一个整数转换为三种进制表示的字符串。
浮点数是有小数部分的数值。浮点数通常使用 C 语言中的双精度浮点数 double 来实现。浮点数也可以使用科学计数法表示。以下各变量均为浮点数类型变量:
import math
a = 3.0
b = .1415
c = -2.78e6
d = 3.14E-2
f = 3 / 2 # 除法运算总是产生一个浮点数
g = 2 * a # 不同类型的二元运算产生的类型总是会被拓宽
h = float("33")
i = math.sin(2) # 该函数的返回类型是浮点数
在计算机中,并不能精确地表示浮点数。即便是最简单的数学运算,也可能带来不可控制的后果。
a = 2.7
b = 4.5
print(a - b == -1.8) # False
print(a - b) # -1.7999999999999998
a = 2.6
print(a + b) # 7.1
要控制浮点数的精度,可以使用 decimal 模块的 Decimal 类型:
from decimal import Decimal
a = Decimal('2.7')
b = Decimal('4.5')
print(a - b) # -1.8
复数包含实部和虚部,各以一个浮点数表示,其中虚部以 j 或 J 结尾。要从一个复数 z 中提取这两个部分,可使用 z.real 和 z.imag。以下各变量均为复数类型变量:
a = 3.3 + 2.7j
b = -4.5J
c = a + b
d = c.real - c.imag*1.0j
e = a * b
f = complex(3.3, 2.7)
g = complex("3.3+2.7j") # 注意加号两侧不能有空格
字符串类型#
字符串是由零个或多个字符组成的有限序列。字符串用于文本信息(如你的姓名)或任意的字节集合(如图片文件的内容)。
字符串字面量#
字符串的字面量有多种不同的写法:
- 单引号包围的文字,如
'hello'、'西安科技大学'、'Einstein wrote: "God does not play dice with the universe"'; - 双引号包围的文字,如
"hello"、"西安科技大学"、"Xi'an"; - 三重引号:
'''三重单引号'''或"""三重双引号"""。使用三重引号的字符串可以跨越多行,其中所有的空白字符都将包含在该字符串字面值中。见下页示例。
三重引号表示的字符串,其中可以包含回车和换行符:
python = '''
______ _ _
| ___ \ | | | |
| |_/ / _| |_| |__ ___ _ __
| __/ | | | __| '_ \ / _ \| '_ \
| | | |_| | |_| | | | (_) | | | |
\_| \__, |\__|_| |_|\___/|_| |_|
__/ |
|___/
'''
print(python)
字符串序列的操作#
获取长度
字符串作为序列,像列表、元组一样,支持一些序列特有的操作,如获取长度、索引、切分和拼接。这些操作对其他序列也适用。
可通过内置的 len() 函数获取字符串的长度(元素个数),该函数同样可用于其他序列和集合类型。如下所示:
>>> s = 'Hello'
>>> len(s)
5
>>> xust = '西安科技大学'
>>> len(xust)
6
索引
字符串的每个字符元素都有一个整数类型的数值偏移量,其中第一个字符的偏移量为 0, 第二个为 1,依此类推。可以通过 s[i] 的形式获得字符串 s 中偏移量为 i 的字符所构成的单字符字符串,此即字符串的索引。
此外,Python 的字符串还支持反向索引,即从最后一个字符开始用负整数计数,最后一个字符的索引为 -1,倒数第二个是 -2,依此类推。
>>> s = 'Hello'
>>> s[0]
'H'
>>> s[1]
'e'
>>> s[-1]
'o'
>>> s[-2]
'l'
>>> s[len(s)-1]
'o'
# Python 中没有专门的字符类型,因此字符串的每项索引结果是长度为 1 的字符串
>>> type(s[0])
<class 'str'>
分片
可以对字符串进行切分操作,得到字符串的一个分片(或称切片),此分片是一个子字符串。
其常规形式是 s[i:j],表示取得在字符串 s 中从偏移量 i 开始,到偏移量 j 结束(不包括 j)的字符串内容。
也可以省略 i 或 j,省略 i 时,其值默认为 0,省略 j 时,其值默认为字符串的长度 len(s)。
>>> s = 'Hello'
>>> s[1:3] # 获得偏移量 [1, 3) 范围内的切片
'el'
>>> s[:3] # 获得偏移量 [0, 3) 范围内的切片
'Hel'
>>> s[1:] # 获得偏移量 [1, len(s)) 范围内的切片
'ello'
>>> s[:] # 获得偏移量 [0, len(s)) 范围内的切片
'Hello'
>>> s[:-1] # 获得偏移量 [0, len(s)-1) 范围内的切片
'Hell'
拼接
可以使用加号 + 对字符串进行拼接(Concatenation),即将两个字符串合并成一个字符串;也可以使用乘号 * 将字符串重复多次以创建一个新的字符串。
>>> 'Hello,' + ' world!'
'Hello, world!'
>>> '-' * 80
'--------------------------------------------------------------------------------'
在表达式中,之间只由空格分隔的多个字符串字面值会被隐式地拼接为单个字符串字面值。如下所示:
>>> 'abc' "def"
'abcdef'
字符串是不可变的#
字符串值是不可变的,即在创建后,不能原位改变其内容。以下操作时不允许的:
>>> s = 'Hello'
>>> s[1] = 'o' # 将会出现错误
要改变一个字符串变量,必须重新为其赋值。
>>> s[:4] + ' world!'
'Hell world!'
转义#
字符串中有一些特殊字符,由于不便输入,经常需要以转义(Escape)的形式输入,即用一个反斜杠 \ 后跟一个或多个ASCII 字符表示该字符串。Python 支持如下转义字符:
| 转义序列 | 含意 | 转义序列 | 含意 |
|---|---|---|---|
\<换行> |
不进行换行 | \\ |
反斜杠(\) |
\' |
单引号(') |
\" |
双引号(") |
\a |
响铃(BEL) | \b |
退格符(BS) |
\n |
换行符(LF) | \r |
回车符(CR) |
\t |
水平制表符(TAB) | \v |
垂直制表符(VT) |
\f |
换页符(FF) | \N{name} |
Unicode 数据库中名为 name 的字符 |
\ooo |
后紧跟最多 3 个八进制数字 ooo | \xhh |
后紧跟 2 个十六进制数字 hh |
\uhhhh |
后紧跟 4 个十六进制数字 hhhh | \Uhhhhhhhh |
后紧跟 8 个十六进制数字 hhhhhhhh |
可以在字符串的左引号前面加一个 r,不让字符串进行转义,这样的字符串称为原始字符串。
字符串转义使用示例:
s = 'Xi\'an'
print(s) # Xi'an
s = 'Hello, \
world!'
print(s) # Hello, world!
s = 'Hello, \nworld!'
# Hello,
# world!
print(s)
s = 'Hello,\tworld!'
print(s) # Hello, world!
s = 'Hello,\b\b world!'
将其他对象转换为字符串#
Python 设计的座右铭之一是拒绝猜测,如下面将字符串和数字相加,因无法知道执行的是数字加法还是字符串拼接,因此会报错:
>>> 33 + '44'
TypeError: unsupported operand type(s) for +: 'int' and 'str'
要想执行字符串拼接,可以使用内置函数 str 将数字转换为字符串:
>>> str(33) + '44'
'3344'
还有另外一个内置函数 repr 也能将对象转换为字符串,但它返回的是可作为代码的字符串对象,请自行学习。
字符串的方法#
Python 有一组可以在字符串上使用的内建方法,即字符串的方法,可以采用如下方式调用字符串的方法:
字符串对象.方法名称(参数列表)
示例如下:
>>> s = 'Hello, world!'
>>> s.upper() # upper() 方法把字符串转换为大写
'HELLO, WORLD!'
>>> s.replace('world', '世界') # 将字符串中出现的所有 'world' 子字符串替换为 '世界'
'Hello, 世界!'
字符串的方法有很多个,请自行查看并了解各个方法的功能。
字符串格式化#
在编程时,经常需要根据数据对象的值动态生成具有复杂格式的文本,这就需要用到字符串格式化。字符串格式化允许在单个步骤中对一个字符串执行多个特定类型的替换。
Python 支持三种形式的字符串格式化:
-
字符串格式化表达式,形如:
'...%s...' % (values)从 Python 诞生的时候就有的最初技术,其形式是基于 C 语言的printf函数模型。 -
字符串格式化方法调用,形如:
'...{}...'.format(values)Python 2.6/3.0 新增的技术,其形式部分起源于 C#/.NET 中的同名工具;其主要使用字符串的 format() 方法进行格式化。
-
格式字符串字面值,形如:
f'...{value}...'又称 f-string,这是 Python 3.6 新增的技术。相对于前两者,其更简单和直观,效率也更高。
这三种字符串格式化方法提供的功能都比较相似,尤其是后两者。他们都可以提供复杂的格式化功能,需要花较多的功夫学习掌握。限于篇幅,这里只在下页中对三种方法给出一个简单的例子,然后再简要地介绍第三种 f-string 的用法。
要更深入地了解 f-string 方法,请先阅读这个简单的教程,再进一步阅读器参考手册,最好根据需要阅读此格式规格迷你语言。
三种字符串格式化方法示例:
student = '小明'
course = '高等数学'
score = 92.3
# 字符串格式化表达式
s = '%s 的 %s 考了 %.1f 分。' % (student, course, score)
print(s)
# 字符串格式化方法调用
s = '{} 的 {} 考了 {:.1f} 分。'.format(student, course, score)
print(s)
# 格式字符串字面值(f-string)
s = f'{student} 的 {course} 考了 {score:.1f} 分。'
print(s)
# 均打印:小明 的 高等数学 考了 92.3 分。
要使用 f-string 方法,需要在字符串开头的引号/三引号前添加 f 或 F,然后在字符串中用 {expression} 表示将要被替换的表达式,之后该大括号内的表达式将被求值,并将该值转换而成的字符串替换大括号位置。如下所示:
year = 2022
place = '四川泸定县'
event = '地震'
s = f'{year}年,在{place}发生了一次{event}。'
print(s) # 2022年,在四川泸定县发生了一次地震。
f-string 是在运行时被求值的,你可以在其中放入任意有效的表达式:
print(f'{2 + 2 * 4}') # 10
print(f'{abs(-33)}') # 33
可以为表达式指定格式,这通过在表达式后加一个冒号 :,然后附加格式规格实现。如下所示:
import math
print(f'π 的值为:{math.pi:.3f}。')
scores = {'Zhang-San': 76.5, 'Li-Si': 83.0, 'Wang-Laowu': 66.8}
for name, score in scores.items():
print(f'{name:>10} ==> {score:6.1f}分')
# Zhang-San ==> 76.5分
# Li-Si ==> 83.0分
# Wang-Laowu ==> 66.8分
以上 {math.pi:.3f} 中的 f 表示以十进制浮点数呈现对象,.3 表示小数点后保留三个数字。{name:>10} 中的 10 表示强制该项占据 10 个字符的宽度(不足部分补空格),> 表示右对齐(字符串默认为左对齐)。{score:6.1f} 中的 6 表示强制该项占据 6 个字符的宽度,.1f 表示以十进制浮点数呈现对象,且小数点后保留 1 位。
更多格式规格示例:
x = -0.0314
print(f'{x:e}') # 以科学记数法显示浮点数,以小写 e 分割系数和指数
print(f'{x:E}') # 以科学记数法显示浮点数,以大写 E 分割系数和指数
print(f'{x:.2%}') # 以百分数形式显示浮点数,且小数点后保留 2 位
n = 66
print(f'{n:b}') # 以二进制格式显示整数
print(f'{n:0>9_b}') # 以二进制格式显示整数,总宽度为 9,不足部分补 0,右对齐,每 4 位用下划线分割
print(f'{n:+d}') # 以十进制格式显示整数,总是在其前方加正号或负号
请自行运行示例查看显示结果。更详细的格式语法,请参见格式规格迷你语言。
布尔类型#
布尔是计算机科学中的逻辑数据类型,以发明布尔代数的数学家乔治·布尔为名。它是只有两种值的原始类型,通常是真和假。在 Python 中,他们对应两个字面量,分别是 True 和 False(注意首字母必须为大写)。
比较运算、逻辑运算会产生布尔类型值,Python 的 if 语句和 while 语句都需要一个布尔类型的表达式作为控制语句流向的判别式。如下所示:
n = int(input('请输入一个数字:'))
b = n > 50 # n 是一个布尔类型值
if b:
print('你输入的数字', n, '大于 50。')
else:
print('你输入的数字', n, '小于 50。')
在 Python 中,可以把所有对象用在需要布尔值的场合,只有下面的几种情况得到的值为假:
- 被定义为假值的常量: None 和 False。
- 任何数值类型的零: 0, 0.0, 0j, Decimal(0), Fraction(0, 1)
- 空的序列和多项集: ‘’, (), [], {}, set(), range(0)
示例如下:
n = int(input('请输入一个数字:'))
if n:
print('你输入的数字不为零。')
else:
print('你输入的数字为零。')
前面说过,布尔类型属于整数的子类型,这表示你可以把布尔类型值用在需要数字的场合进行数值计算,这时 True 代表 1,False 代表 0。如下所示
>>> False + 2
2
>>> True + 2
3