内置类型
以下部分描述了解释器中内置的标准类型。
主要内置类型有数字、序列、映射、类、实例和异常。
有些多项集类是可变的。 它们用于添加、移除或重排其成员的方法将原地执行,并不返回特定的项,绝对不会返回多项集实例自身而是返回 None
。
有些操作受多种对象类型的支持;特别地,实际上所有对象都可以比较是否相等、检测逻辑值,以及转换为字符串(使用 repr()
函数或略有差异的 str()
函数)。 后一个函数是在对象由 print()
函数输出时被隐式地调用的。
逻辑值检测
任何对象都可以进行逻辑值的检测,以便在 if
或 while
作为条件或是作为下文所述布尔运算的操作数来使用。
在默认情况下,一个对象会被视为具有真值,除非其所属的类定义了在对象上调用时返回 False
的 __bool__()
方法或者返回零的 __len__()
方法。 [1] 以下基本完整地列出了具有假值的内置对象:
被定义为假值的常量:
None
和False
任何数值类型的零:
0
,0.0
,0j
,Decimal(0)
,Fraction(0, 1)
空的序列和多项集:
''
,()
,[]
,{}
,set()
,range(0)
产生布尔值结果的运算和内置函数总是返回 0
或 False
作为假值,1
或 True
作为真值,除非另行说明。 (重要例外:布尔运算 or
和 and
总是返回其中一个操作数。)
布尔运算 —- and
, or
, not
这些属于布尔运算,按优先级升序排列:
运算 | 结果: | 备注 |
---|---|---|
x or y
| 如果 x 为真值,则 x,否则 y | (1) |
x and y
| if x is false, then x, else y | (2) |
not x
|
if x is false, then True , else False
| (3) |
注释:
这是个短路运算符,因此只有在第一个参数为假值时才会对第二个参数求值。
这是个短路运算符,因此只有在第一个参数为真值时才会对第二个参数求值。
not
的优先级比非布尔运算符低,因此not a == b
会被解读为not (a == b)
而a == not b
会引发语法错误。
比较运算
在 Python 中有八种比较运算符。 它们的优先级相同(比布尔运算的优先级高)。 比较运算可以任意串连;例如,x < y <= z
等价于 x < y and y <= z
,前者的不同之处在于 y 只被求值一次(但在两种情况下当 x < y
结果为假值时 z 都不会被求值)。
此表格汇总了比较运算:
运算 | 含意 |
---|---|
<
| 严格小于 |
<=
| 小于或等于 |
>
| 严格大于 |
>=
| 大于或等于 |
==
| 等于 |
!=
| 不等于 |
is
| 对象标识 |
is not
| 否定的对象标识 |
除不同的数字类型外,不同类型的对象不能进行相等比较。==
运算符总有定义,但对于某些对象类型(例如,类对象),它等于 is
。其他 <
、<=
、>
和 >=
运算符仅在有意义的地方定义。例如,当参与比较的参数之一为复数时,它们会抛出 TypeError
异常。
具有不同标识的类的实例比较结果通常为不相等,除非类定义了 __eq__()
方法。
一个类的实例不能与相同类的其他实例或其他类型的对象进行排序,除非定义该类定义了足够多的方法,包括 __lt__()
, __le__()
, __gt__()
以及 __ge__()
(而如果你想实现常规意义上的比较操作,通常只要有 __lt__()
和 __eq__()
就可以了)。
is
和 is not
运算符无法自定义;并且它们可以被应用于任意两个对象而不会引发异常。
还有两种具有相同语法优先级的运算 in
和 not in
,它们被 iterable 或实现了 __contains__()
方法的类型所支持。
数字类型 —- int
, float
, complex
存在三种不同的数字类型: 整数, 浮点数 和 复数。 此外,布尔值属于整数的子类型。 整数具有无限的精度。 浮点数通常使用 C 中的 double 来实现;有关你的程序运行所在机器上浮点数的精度和内部表示法可在 sys.float_info
中查看。 复数包含实部和虚部,分别以一个浮点数表示。 要从一个复数 z 中提取这两个部分,可使用 z.real
和 z.imag
。 (标准库包含附加的数字类型,如表示有理数的 fractions.Fraction
以及以用户定制精度表示浮点数的 decimal.Decimal
。)
数字是由数字字面值或内置函数与运算符的结果来创建的。 不带修饰的整数字面值(包括十六进制、八进制和二进制数)会生成整数。 包含小数点或幂运算符的数字字面值会生成浮点数。 在数字字面值末尾加上 'j'
或 'J'
会生成虚数(实部为零的复数),你可以将其与整数或浮点数相加来得到具有实部和虚部的复数。
Python 完全支持混合运算:当一个二元算术运算符的操作数有不同数值类型时,"较窄"类型的操作数会拓宽到另一个操作数的类型,其中整数比浮点数窄,浮点数比复数窄。不同类型的数字之间的比较,同比较这些数字的精确值一样。[2]
构造函数 int()
、 float()
和 complex()
可以用来构造特定类型的数字。
所有数字类型(复数除外)都支持下列运算(有关运算优先级,请参阅:运算符优先级):
运算 | 结果: | 备注 | 完整文档 |
---|---|---|---|
x + y
| x 和 y 的和 | ||
x - y
| x 和 y 的差 | ||
x * y
| x 和 y 的乘积 | ||
x / y
| x 和 y 的商 | ||
x // y
| x 和 y 的商数 | (1)(2) | |
x % y
|
x / y 的余数
| (2) | |
-x
| x 取反 | ||
+x
| x 不变 | ||
abs(x)
| x 的绝对值或大小 |
abs()
| |
int(x)
| 将 x 转换为整数 | (3)(6) |
int()
|
float(x)
| 将 x 转换为浮点数 | (4)(6) |
float()
|
complex(re, im)
| 一个带有实部 re 和虚部 im 的复数。im 默认为0。 | (6) |
complex()
|
c.conjugate()
| 复数 c 的共轭 | ||
divmod(x, y)
|
(x // y, x % y)
| (2) |
divmod()
|
pow(x, y)
| x 的 y 次幂 | (5) |
pow()
|
x ** y
| x 的 y 次幂 | (5) |
注释:
也称为整数除法。 对于
int
类型的操作数,结果的类型为int
。 对于float
类型的操作数,结果的类型为float
。 总的说来,结果是一个整数,但结果的类型不一定为int
。 结果总是向负无穷的方向舍入:1//2
为0
,(-1)//2
为-1
,1//(-2)
为-1
,(-1)//(-2)
为0
。不可用于复数。 而应在适当条件下使用
abs()
转换为浮点数。从
float
转换为int
将会执行截断,丢弃掉小数部分。 请参阅math.floor()
和math.ceil()
函数了解替代的转换方式。float 也接受字符串 "nan" 和附带可选前缀 "+" 或 "-" 的 "inf" 分别表示非数字 (NaN) 以及正或负无穷。
Python 将
pow(0, 0)
和0 ** 0
定义为1
,这是编程语言的普遍做法。接受的数字字面值包括数码
0
到9
或任何等效的 Unicode 字符(具有Nd
特征属性的代码点)。
请参阅 Unicode 标准 [https://unicode.org/Public/UNIDATA/extracted/DerivedNumericType.txt] 了解具有 Nd
特征属性的码位完整列表。
所有 numbers.Real
类型 (int
和 float
) 还包括下列运算:
运算 | 结果: |
---|---|
math.trunc(x)
|
x 截断为 Integral
|
round(x[,
n])
| x 舍入到 n 位小数,半数值会舍入到偶数。 如果省略 n,则默认为 0。 |
math.floor(x)
|
<= x 的最大 Integral
|
math.ceil(x)
|
>= x 的最小 Integral
|
整数类型的按位运算
按位运算只对整数有意义。 计算按位运算的结果,就相当于使用无穷多个二进制符号位对二的补码执行操作。
二进制按位运算的优先级全都低于数字运算,但又高于比较运算;一元运算 ~
具有与其他一元算术运算 (+
and -
) 相同的优先级。
此表格是以优先级升序排序的按位运算列表:
运算 | 结果: | 备注 |
---|---|---|
x | y
| x 和 y 按位 或 | (4) |
x ^ y
| x 和 y 按位 异或 | (4) |
x & y
| x 和 y 按位 与 | (4) |
x << n
| x 左移 n 位 | (1)(2) |
x >> n
| x 右移 n 位 | (1)(3) |
~x
| x 逐位取反 |
注释:
负的移位数是非法的,会导致引发
ValueError
。左移 n 位等价于乘以
pow(2, n)
。右移 n 位等价于除以
pow(2, n)
,作向下取整除法。使用带有至少一个额外符号扩展位的有限个二进制补码表示(有效位宽度为
1 + max(x.bit_length(), y.bit_length())
或以上)执行这些计算就足以获得相当于有无数个符号位时的同样结果。
整数类型的附加方法
int 类型实现了 numbers.Integral
abstract base class。 此外,它还提供了其他几个方法:
- int.bit_length()
- 返回以二进制表示一个整数所需要的位数,不包括符号位和前面的零:
- >>> n = -37
- >>> bin(n)
- '-0b100101'
- >>> n.bit_length()
- 6
更准确地说,如果 x
非零,则 x.bit_length()
是使得 2**(k-1) <= abs(x) < 2**k
的唯一正整数 k
。 同样地,当 abs(x)
小到足以具有正确的舍入对数时,则 k = 1 + int(log(abs(x), 2))
。 如果 x
为零,则 x.bit_length()
返回 0
。
等价于:
- def bit_length(self):
- s = bin(self) # 二进制表示形式: bin(-37) --> '-0b100101'
- s = s.lstrip('-0b') # 移除开头的零和负号
- return len(s) # len('100101') --> 6
Added in version 3.1.
- int.bit_count()
- 返回整数的绝对值的二进制表示中 1 的个数。也被称为 population count。示例:
- >>> n = 19
- >>> bin(n)
- '0b10011'
- >>> n.bit_count()
- 3
- >>> (-n).bit_count()
- 3
等价于:
- def bit_count(self):
- return bin(self).count("1")
Added in version 3.10.
- int.to_bytes(length=1, byteorder='big', *, signed=False)
- 返回表示一个整数的字节数组。
- >>> (1024).to_bytes(2, byteorder='big')
- b'\x04\x00'
- >>> (1024).to_bytes(10, byteorder='big')
- b'\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00'
- >>> (-1024).to_bytes(10, byteorder='big', signed=True)
- b'\xff\xff\xff\xff\xff\xff\xff\xff\xfc\x00'
- >>> x = 1000
- >>> x.to_bytes((x.bit_length() + 7) // 8, byteorder='little')
- b'\xe8\x03'
整数会使用 length 个字节来表示,默认为 1。 如果整数不能用给定的字节数来表示则会引发 OverflowError
。
byteorder 参数确定用于表示整数的字节顺序,默认为 "big"
。 如果 byteorder 为 "big"
,则最高位字节放在字节数组的开头。 如果 byteorder 为 "little"
,则最高位字节放在字节数组的末尾。
signed 参数确定是否使用二的补码来表示整数。 如果 signed 为 False
并且给出的是负整数,则会引发 OverflowError
。 signed 的默认值为 False
。
默认值可用于方便地将整数转为一个单字节对象:
- >>> (65).to_bytes()
- b'A'
但是,当使用默认参数时,请不要试图转换大于 255 的值否则会引发 OverflowError
。
等价于:
- def to_bytes(n, length=1, byteorder='big', signed=False):
- if byteorder == 'little':
- order = range(length)
- elif byteorder == 'big':
- order = reversed(range(length))
- else:
- raise ValueError("byteorder must be either 'little' or 'big'")
- return bytes((n >> i*8) & 0xff for i in order)
Added in version 3.2.
在 3.11 版本发生变更: 添加了 length
和 byteorder
的默认参数值。
- classmethod int.from_bytes(bytes, byteorder='big', *, signed=False)
- 返回由给定字节数组所表示的整数。
- >>> int.from_bytes(b'\x00\x10', byteorder='big')
- 16
- >>> int.from_bytes(b'\x00\x10', byteorder='little')
- 4096
- >>> int.from_bytes(b'\xfc\x00', byteorder='big', signed=True)
- -1024
- >>> int.from_bytes(b'\xfc\x00', byteorder='big', signed=False)
- 64512
- >>> int.from_bytes([255, 0, 0], byteorder='big')
- 16711680
bytes 参数必须为一个 bytes-like object 或是生成字节的可迭代对象。
byteorder 参数确定用于表示整数的字节顺序,默认为 "big"
。 如果 byteorder 为 "big"
,则最高位字节放在字节数组的开头。 如果 byteorder 为 "little"
,则最高位字节放在字节数组的末尾。 要请求主机系统上的原生字节顺序,请使用 sys.byteorder
作为字节顺序值。
signed 参数指明是否使用二的补码来表示整数。
等价于:
- def from_bytes(bytes, byteorder='big', signed=False):
- if byteorder == 'little':
- little_ordered = list(bytes)
- elif byteorder == 'big':
- little_ordered = list(reversed(bytes))
- else:
- raise ValueError("byteorder must be either 'little' or 'big'")
- n = sum(b << i*8 for i, b in enumerate(little_ordered))
- if signed and little_ordered and (little_ordered[-1] & 0x80):
- n -= 1 << 8*len(little_ordered)
- return n
Added in version 3.2.
在 3.11 版本发生变更: 添加了 byteorder
的默认参数值。
- int.as_integer_ratio()
- 返回一对整数,其比率正好等于原整数并且分母为正数。 整数的比率总是用这个整数本身作为分子并以
1
作为分母。
Added in version 3.8.
- int.is_integer()
- 返回
True
。 存在于兼容float.is_integer()
的鸭子类型。
Added in version 3.12.
浮点类型的附加方法
float 类型实现了 numbers.Real
abstract base class。 float 还具有以下附加方法。
- float.as_integer_ratio()
- 返回一对整数,其比率正好等于原浮点数。 该比率为最简形式且分母为正值。 无穷大会引发
OverflowError
而 NaN 则会引发ValueError
。
- float.is_integer()
- 如果 float 实例可用有限位整数表示则返回
True
,否则返回False
:
- >>> (-2.0).is_integer()
- True
- >>> (3.2).is_integer()
- False
两个方法均支持与十六进制数字符串之间的转换。 由于 Python 浮点数在内部存储为二进制数,因此浮点数与 十进制数 字符串之间的转换往往会导致微小的舍入错误。 而十六进制数字符串却允许精确地表示和描述浮点数。 这在进行调试和数值工作时非常有用。
- float.hex()
- 以十六进制字符串的形式返回一个浮点数表示。 对于有限浮点数,这种表示法将总是包含前导的
0x
和尾随的p
加指数。
- classmethod float.fromhex(s)
- 返回以十六进制字符串 s 表示的浮点数的类方法。 字符串 s 可以带有前导和尾随的空格。
请注意 float.hex()
是实例方法,而 float.fromhex()
是类方法。
十六进制字符串采用的形式为:
- [sign] ['0x'] integer ['.' fraction] ['p' exponent]
可选的 sign
可以是 +
或 -
,integer
和 fraction
是十六进制数码组成的字符串,exponent
是带有可选前导符的十进制整数。 大小写没有影响,在 integer 或 fraction 中必须至少有一个十六进制数码。 此语法类似于 C99 标准的 6.4.4.2 小节中所描述的语法,也是 Java 1.5 以上所使用的语法。 特别地,float.hex()
的输出可以用作 C 或 Java 代码中的十六进制浮点数字面值,而由 C 的 %a
格式字符或 Java 的 Double.toHexString
所生成的十六进制数字符串由为 float.fromhex()
所接受。
请注意 exponent 是十进制数而非十六进制数,它给出要与系数相乘的 2 的幂次。 例如,十六进制数字符串 0x3.a7p10
表示浮点数 (3 + 10./16 + 7./16**2) * 2.0**10
即 3740.0
:
- >>> float.fromhex('0x3.a7p10')
- 3740.0
对 3740.0
应用反向转换会得到另一个代表相同数值的十六进制数字符串:
- >>> float.hex(3740.0)
- '0x1.d380000000000p+11'
数字类型的哈希运算
对于可能为不同类型的数字 x
和 y
,要求当 x == y
时必定有 hash(x) == hash(y)
(详情参见 __hash__()
方法的文档)。 为了便于在各种数字类型 (包括 int
, float
, decimal.Decimal
和 fractions.Fraction
) 上实现并保证效率,Python 对数字类型的哈希运算是基于为任意有理数定义统一的数学函数,因此该运算对 int
和 fractions.Fraction
的全部实例,以及 float
和 decimal.Decimal
的全部有限实例均可用。 从本质上说,此函数是通过以一个固定质数 P
进行 P
降模给出的。 P
的值在 Python 中可以 sys.hash_info
的 modulus
属性的形式被访问。
目前所用的质数设定,在 C long 为 32 位的机器上 P = 2**31 - 1
而在 C long 为 64 位的机器上 P = 2**61 - 1
。
详细规则如下所述:
如果
x = m / n
是一个非负的有理数且n
不可被P
整除,则定义hash(x)
为m * invmod(n, P) % P
,其中invmod(n, P)
是对n
模P
取反。如果
x = m / n
是一个非负的有理数且n
可被P
整除(但m
不能)则n
不能对P
降模,以上规则不适用;在此情况下则定义hash(x)
为常数值sys.hash_info.inf
。如果
x = m / n
是一个负的有理数则定义hash(x)
为-hash(-x)
。 如果结果哈希值为-1
则将其替换为-2
。特殊值
sys.hash_info.inf
和-sys.hash_info.inf
分别用于正无穷或负无穷的哈希值。对于一个
complex
值z
,会通过计算hash(z.real) + sys.hash_info.imag * hash(z.imag)
将实部和虚部的哈希值结合起来,并进行降模2**sys.hash_info.width
以使其处于range(-2**(sys.hash_info.width - 1), 2**(sys.hash_info.width - 1))
范围之内。 同样地,如果结果为-1
则将其替换为-2
。
为了阐明上述规则,这里有一些等价于内置哈希算法的 Python 代码示例,可用于计算有理数、float
或 complex
的哈希值:
- import sys, math
- def hash_fraction(m, n): """Compute the hash of a rational number m / n.
- Assumes m and n are integers, with n positive.
- Equivalent to hash(fractions.Fraction(m, n)).
- """
- P = sys.hash_info.modulus
- # 移除 P 的公因数。 (如果 m 和 n 互质则不需要。)
- while m % P == n % P == 0:
- m, n = m // P, n // P
- if n % P == 0:
- hash_value = sys.hash_info.inf
- else:
- # 费马小定理: pow(n, P-1, P) 等于 1,
- # 则 pow(n, P-2, P) 等于 n 除以 P 的余数的倒数。
- hash_value = (abs(m) % P) * pow(n, P - 2, P) % P
- if m < 0:
- hash_value = -hash_value
- if hash_value == -1:
- hash_value = -2
- return hash_value
- def hash_float(x): """Compute the hash of a float x."""
- if math.isnan(x):
- return object.__hash__(x)
- elif math.isinf(x):
- return sys.hash_info.inf if x > 0 else -sys.hash_info.inf
- else:
- return hash_fraction(*x.as_integer_ratio())
- def hash_complex(z): """Compute the hash of a complex number z."""
- hash_value = hash_float(z.real) + sys.hash_info.imag * hash_float(z.imag)
- # 带正负号的约减求余运算 2**sys.hash_info.width
- M = 2**(sys.hash_info.width - 1)
- hash_value = (hash_value & (M - 1)) - (hash_value & M)
- if hash_value == -1:
- hash_value = -2
- return hash_value
布尔类型 - bool
代表真值的布尔对象。 bool
类型只有两个常量实例: True
和 False
。
内置函数 bool()
可将任意值转换为布尔值,如果该值可以被解读为逻辑值的话(参见上面的 逻辑值检测 小节)。
对于逻辑运算,请使用 布尔运算符 and
, or
和 not
。 当于两个布尔值应用按位运算符 &
, |
, ^
时,它们将返回一个等价于逻辑运算 "与", "或", "异或" 的布尔值。 但是,更推荐使用逻辑运算符 and
, or
和 !=
而不是 &
, |
和 ^
。
自 3.12 版本弃用: 使用按位取反运算符 ~
已被弃用并将在 Python 3.16 中引发错误。
bool
是 int
的子类 (参见 数字类型 —- int, float, complex)。 在许多数字场景下,False
和 True
的行为分别与整数 0 和 1 类似。 但是,不建议这样使用;请使用 int()
显式地执行转换。
迭代器类型
Python 支持在容器中进行迭代的概念。 这是通过使用两个单独方法来实现的;它们被用于允许用户自定义类对迭代的支持。 将在下文中详细描述的序列总是支持迭代方法。
容器对象要提供 iterable 支持,必须定义一个方法:
- container.iter()
- 返回一个 iterator 对象。 该对象需要支持下文所述的迭代器协议。 如果容器支持不同的迭代类型,则可以提供额外的方法来专门地请求不同迭代类型的迭代器。 (支持多种迭代形式的对象的例子有同时支持广度优先和深度优先遍历的树结果。) 此方法对应于 Python/C API 中 Python 对象类型结构体的
tp_iter
槽位。
迭代器对象自身需要支持以下两个方法,它们共同组成了 迭代器协议:
- iterator.iter()
- 返回 iterator 对象本身。 这是同时允许容器和迭代器配合
for
和in
语句使用所必须的。 此方法对应于 Python/C API 中 Python 对象类型结构体的tp_iter
槽位。
- iterator.next()
- iterator 中返回下一项。 如果已经没有可返回的项,则会引发
StopIteration
异常。 此方法对应于 Python/C API 中 Python 对象类型结构体的tp_iternext
槽位。
Python 定义了几种迭代器对象以支持对一般和特定序列类型、字典和其他更特别的形式进行迭代。 除了迭代器协议的实现,特定类型的其他性质对迭代操作来说都不重要。
一旦迭代器的 __next__()
方法引发了 StopIteration
,它必须一直对后续调用引发同样的异常。 不遵循此行为特性的实现将无法正常使用。
生成器类型
Python 的 generator 提供了一种实现迭代器协议的便捷方式。 如果容器对象的 __iter__()
方法以生成器形式实现,它将自动返回一个迭代器对象(从技术上说是一个生成器对象),该对象提供 __iter__()
和 __next__()
方法。 有关生成器的更多信息可以参阅 yield 表达式的文档。
序列类型 —- list
, tuple
, range
有三种基本序列类型:list, tuple 和 range 对象。 为处理 二进制数据 和 文本字符串 而特别定制的附加序列类型会在专门的小节中描述。