内置类型¶
以下各节介绍了解释器内置的标准类型。
主要的内置类型是数字、序列、映射、类、实例和异常。
某些集合类是可变的。那些原地添加、移除或重排成员且不返回特定项的方法,永远不会返回集合实例本身,而是返回 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* 为真,则返回 *x*,否则返回 *y* |
(1) |
|
如果 *x* 为假,则返回 *x*,否则返回 *y* |
(2) |
|
如果 *x* 为假,则返回 |
(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
。 <
, <=
, >
和 >=
运算符仅在它们有意义时定义;例如,当其中一个参数是复数时,它们会引发 TypeError
异常。
一个类的不同实例通常比较为不相等,除非该类定义了 __eq__()
方法。
类的实例不能相对于同一类的其他实例或其他类型的对象进行排序,除非该类定义了足够多的方法 __lt__()
, __le__()
, __gt__()
, 和 __ge__()
(通常,如果你想要比较运算符的常规含义,__lt__()
和 __eq__()
就足够了)。
is
和 is not
运算符的行为无法自定义;此外,它们可以应用于任何两个对象,并且永远不会引发异常。
另外两个具有相同语法优先级的操作 in
和 not in
,由 可迭代 的类型或实现了 __contains__()
方法的类型支持。
数字类型 — int
, float
, complex
¶
有三种不同的数字类型:整数,浮点数,和复数。此外,布尔值是整数的一个子类型。整数具有无限精度。浮点数通常使用 C 中的 double 实现;有关机器上浮点数的精度和内部表示的信息,请参阅 sys.float_info
。复数具有实部和虚部,它们都是浮点数。要从复数 *z* 中提取这些部分,请使用 z.real
和 z.imag
。(标准库包含额外的数字类型 fractions.Fraction
(用于有理数) 和 decimal.Decimal
(用于用户可定义精度的浮点数)。)
数字可以通过数字字面量创建,或者作为内置函数和运算符的结果创建。无装饰的整数字面量(包括十六进制、八进制和二进制数字)产生整数。包含小数点或指数符号的数字字面量产生浮点数。在数字字面量后附加 'j'
或 'J'
会产生一个虚数(实部为零的复数),您可以将其加到一个整数或浮点数上以得到一个具有实部和虚部的复数。
构造函数 int()
, float()
, 和 complex()
可用于生成特定类型的数字。
Python 完全支持混合算术:当一个二元算术运算符的两个操作数是不同数字类型时,较“窄”类型的操作数会被提升为与另一个操作数相同的类型,其中整数比浮点数窄。复数与实数算术按照常规数学公式定义,例如
x + complex(u, v) = complex(x + u, v)
x * complex(u, v) = complex(x * u, x * v)
不同类型数字之间的比较,就好像在比较这些数字的精确值一样。[2]
所有数字类型(复数除外)都支持以下操作(有关操作优先级,请参阅 运算符优先级)
操作 |
结果 |
备注 |
完整文档 |
---|---|---|---|
|
*x* 和 *y* 的和 |
||
|
*x* 和 *y* 的差 |
||
|
*x* 和 *y* 的积 |
||
|
*x* 除以 *y* 的商 |
||
|
*x* 除以 *y* 的地板商 |
(1)(2) |
|
|
*x* / *y* 的余数 |
(2) |
|
|
*x* 的负值 |
||
|
*x* 不变 |
||
|
*x* 的绝对值或大小 |
||
|
*x* 转换为整数 |
(3)(6) |
|
|
*x* 转换为浮点数 |
(4)(6) |
|
|
一个复数,实部为 *re*,虚部为 *im*。*im* 默认为零。 |
(6) |
|
|
复数 *c* 的共轭 |
||
|
对 |
(2) |
|
|
*x* 的 *y* 次幂 |
(5) |
|
|
*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
属性的代码点)。有关
Nd
属性的代码点列表,请参阅 Unicode 标准。
所有 numbers.Real
类型(int
和 float
)还包括以下操作
操作 |
结果 |
---|---|
*x* 截断为 |
|
*x* 四舍五入到 *n* 位,采用四舍五入到偶数。如果省略 *n*,则默认为 0。 |
|
小于或等于 *x* 的最大 |
|
大于或等于 *x* 的最小 |
整数类型的按位运算¶
按位运算只对整数有意义。按位运算的结果被计算为好像是在具有无限符号位的二进制补码中进行的。
二元按位运算的优先级都低于算术运算,高于比较运算;一元运算 ~
具有与其他一元算术运算(+
和 -
)相同的优先级。
下表列出了按位运算,按优先级升序列出
操作 |
结果 |
备注 |
---|---|---|
|
*x* 和 *y* 的按位 *或* |
(4) |
|
*x* 和 *y* 的按位 *异或* |
(4) |
|
*x* 和 *y* 的按位 *与* |
(4) |
|
*x* 左移 *n* 位 |
(1)(2) |
|
*x* 右移 *n* 位 |
(1)(3) |
|
*x* 的位反转 |
备注
负移位计数是非法的,会导致引发
ValueError
。左移 *n* 位等同于乘以
pow(2, n)
。右移 *n* 位等同于地板除以
pow(2, n)
。使用至少一个额外的符号扩展位在有限二进制补码表示中(工作位宽度为
1 + max(x.bit_length(), y.bit_length())
或更大)执行这些计算足以获得与无限个符号位相同的结果。
整数类型的附加方法¶
int 类型实现了 numbers.Integral
抽象基类。此外,它还提供了一些其他方法
- int.bit_length()¶
返回表示整数的二进制位的数量,不包括符号和前导零
>>> n = -37 >>> bin(n) '-0b100101' >>> n.bit_length() 6
更准确地说,如果
x
非零,则x.bit_length()
是唯一的正整数k
,使得2**(k-1) <= abs(x) < 2**k
。等效地,当abs(x)
足够小时,可以正确舍入其对数,则k = 1 + int(log(abs(x), 2))
。如果x
为零,则x.bit_length()
返回0
。等价于:
def bit_length(self): s = bin(self) # binary representation: bin(-37) --> '-0b100101' s = s.lstrip('-0b') # remove leading zeros and minus sign return len(s) # len('100101') --> 6
在 3.1 版本加入。
- int.bit_count()¶
返回整数绝对值的二进制表示中“1”的数量。这也被称为人口计数。例如
>>> n = 19 >>> bin(n) '0b10011' >>> n.bit_count() 3 >>> (-n).bit_count() 3
等价于:
def bit_count(self): return bin(self).count("1")
在 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)
在 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* 必须是 字节类对象 或生成字节的可迭代对象。
*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
在 3.2 版本加入。
已在版本 3.11 中更改: 为
byteorder
添加了默认参数值。
- int.as_integer_ratio()¶
返回一个整数对,其比率等于原始整数,并且分母为正。整数(整数)的整数比始终是整数作为分子,
1
作为分母。在 3.8 版本加入。
- int.is_integer()¶
返回
True
。为与float.is_integer()
的鸭子类型兼容而存在。3.12 新版功能.
浮点数的附加方法¶
float 类型实现了 numbers.Real
抽象基类。float 还具有以下附加方法。
- classmethod float.from_number(x)¶
类方法,用于从数字 *x* 返回一个浮点数。
如果参数是整数或浮点数,则返回具有相同值(在 Python 的浮点精度范围内)的浮点数。如果参数超出 Python 浮点数的范围,将引发
OverflowError
。对于通用 Python 对象
x
,float.from_number(x)
调用x.__float__()
。如果未定义__float__()
,则回退到__index__()
。在 3.14 版本加入。
- float.as_integer_ratio()¶
返回一个整数对,其比率恰好等于原始浮点数。该比率是不可约的,分母为正。对于无穷大,引发
OverflowError
,对于 NaN,引发ValueError
。
- float.is_integer()¶
当浮点实例是有限的且值为整数时返回
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
是带可选符号的十进制整数。大小写不敏感,整数或分数中必须至少有一个十六进制数字。此语法类似于 C99 标准第 6.4.4.2 节中指定的语法,也类似于 Java 1.5 及更高版本中使用的语法。特别是,float.hex()
的输出可以用作 C 或 Java 代码中的十六进制浮点文字,并且 C 的 %a
格式字符或 Java 的 Double.toHexString
产生的十六进制字符串被 float.fromhex()
接受。
请注意,指数以十进制而不是十六进制书写,它表示用于乘以系数的 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'
复数的附加方法¶
complex
类型实现了 numbers.Complex
抽象基类。 complex
还具有以下附加方法。
- classmethod complex.from_number(x)¶
类方法,用于将数字转换为复数。
对于通用 Python 对象
x
,complex.from_number(x)
调用x.__complex__()
。如果未定义__complex__()
,则回退到__float__()
。如果未定义__float__()
,则回退到__index__()
。在 3.14 版本加入。
数字类型的哈希¶
对于数字 x
和 y
,可能类型不同,一个要求是 hash(x) == hash(y)
当且仅当 x == y
(有关更多详细信息,请参阅 __hash__()
方法文档)。为了在各种数字类型(包括 int
, float
, decimal.Decimal
和 fractions.Fraction
)之间易于实现和高效,Python 对数字类型的哈希基于一个单一的数学函数,该函数对任何有理数都已定义,因此适用于 int
和 fractions.Fraction
的所有实例,以及 float
和 decimal.Decimal
的所有有限实例。本质上,该函数由模 P
约简给出,其中 P
是一个固定的素数。 P
的值可通过 Python 的 modulus
属性(位于 sys.hash_info
中)访问。
CPython 实现细节: 当前,在 32 位 C long 的机器上使用的素数是 P = 2**31 - 1
,在 64 位 C long 的机器上使用的素数是 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
# Remove common factors of P. (Unnecessary if m and n already coprime.)
while m % P == n % P == 0:
m, n = m // P, n // P
if n % P == 0:
hash_value = sys.hash_info.inf
else:
# Fermat's Little Theorem: pow(n, P-1, P) is 1, so
# pow(n, P-2, P) gives the inverse of n modulo 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)
# do a signed reduction modulo 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”、“xor”的布尔值。然而,逻辑运算符 and
, or
和 !=
应优先于 &
, |
和 ^
。
已弃用,版本 3.12: 使用按位反转运算符 ~
已弃用,将在 Python 3.16 中引发错误。
bool
是 int
的子类(请参阅 数字类型 — int, float, complex)。在许多数字上下文中,False
和 True
分别表现得像整数 0 和 1。但是,依赖这一点是不鼓励的;最好明确使用 int()
进行转换。
迭代器类型¶
Python 支持一种容器迭代的概念。这是通过两种不同的方法实现的;它们用于允许用户定义的类支持迭代。序列(将在下面更详细地描述)始终支持迭代方法。
需要为容器对象定义一种方法来提供 可迭代 支持
- container.__iter__()¶
返回一个 迭代器 对象。该对象需要支持下面描述的迭代器协议。如果容器支持不同类型的迭代,可以提供其他方法来专门请求这些迭代类型的迭代器。(支持多种迭代形式的对象例如是支持广度优先和深度优先遍历的树结构。)此方法对应于 Python/C API 中 Python 对象类型的
tp_iter
插槽。
迭代器对象本身需要支持以下两个方法,它们共同构成了迭代器协议
- iterator.__iter__()¶
返回 迭代器 对象本身。这对于允许容器和迭代器都用于
for
和in
语句是必需的。此方法对应于 Python/C API 中 Python 对象类型的tp_iter
插槽。
- iterator.__next__()¶
从 迭代器 返回下一个项。如果没有更多项,则引发
StopIteration
异常。此方法对应于 Python/C API 中 Python 对象类型的tp_iternext
插槽。
Python 定义了多种迭代器对象来支持通用和特定序列类型、字典以及其他更专门形式的迭代。具体类型并不重要,除非它们实现了迭代器协议。
一旦迭代器的 __next__()
方法引发 StopIteration
,它必须在后续调用中继续这样做。不遵守此属性的实现被视为有缺陷。
生成器类型¶
Python 的 生成器 提供了一种实现迭代器协议的便捷方式。如果容器对象的 __iter__()
方法被实现为生成器,它将自动返回一个提供 __iter__()
和 __next__()
方法的迭代器对象(技术上是生成器对象)。有关生成器的更多信息可以在 yield 表达式文档 中找到。
序列类型 — list
, tuple
, range
¶
有三种基本序列类型:列表、元组和 range 对象。另外两种针对二进制数据和文本字符串处理量身定制的序列类型在专门的章节中进行了描述。
通用序列操作¶
下表中列出的操作被大多数序列类型(包括可变和不可变类型)支持。 collections.abc.Sequence
ABC 的提供是为了更容易地正确实现这些操作在自定义序列类型上。
下表列出了序列操作,按优先级升序列出。表中,*s* 和 *t* 是同一类型的序列,*n*, *i*, *j*, 和 *k* 是整数,*x* 是任意对象,它满足 *s* 施加的任何类型和值限制。
in
和 not in
操作具有与比较运算相同的优先级。 +
(连接) 和 *
(重复) 操作具有与相应的算术运算相同的优先级。[3]
操作 |
结果 |
备注 |
---|---|---|
|
如果 *s* 的某个项等于 *x*,则为 |
(1) |
|
如果 *s* 的某个项等于 *x*,则为 |
(1) |
|
*s* 和 *t* 的连接 |
(6)(7) |
|
等同于将 *s* 与自身相加 *n* 次 |
(2)(7) |
|
*s* 的第 *i* 项,从 0 开始 |
(3)(8) |
|
从 *i* 到 *j* 的 *s* 的切片 |
(3)(4) |
|
从 *i* 到 *j*、步长为 *k* 的 *s* 的切片 |
(3)(5) |
|
*s* 的长度 |
|
|
*s* 的最小项 |
|
|
*s* 的最大项 |
相同类型的序列也支持比较。特别是,元组和列表通过比较对应元素来进行词典式排序。这意味着要相等,每个元素必须相等,并且两个序列必须是同一类型且长度相同。(有关完整详细信息,请参阅语言参考中的 比较。)
对可变序列的正向和反向迭代器通过索引访问值。即使底层序列被修改,该索引也会继续向前(或向后)移动。迭代器仅在遇到 IndexError
或 StopIteration
时(或当索引降至零以下时)终止。
备注
虽然
in
和not in
操作在一般情况下仅用于简单的包含测试,但一些特殊序列(如str
,bytes
和bytearray
)也使用它们进行子序列测试>>> "gg" in "eggs" True
小于
0
的 *n* 的值被视为0
(这将产生与 *s* 相同类型的空序列)。请注意,序列 *s* 中的项不会被复制;它们被多次引用。这通常会困扰新手 Python 程序员;考虑>>> lists = [[]] * 3 >>> lists [[], [], []] >>> lists[0].append(3) >>> lists [[3], [3], [3]]
发生的情况是
[[]]
是一个包含空列表的单元素列表,因此[[]] * 3
的所有三个元素都是对这个单一空列表的引用。修改lists
的任何元素都会修改这个单一列表。你可以这样创建一个包含不同列表的列表>>> lists = [[] for i in range(3)] >>> lists[0].append(3) >>> lists[1].append(5) >>> lists[2].append(7) >>> lists [[3], [5], [7]]
有关进一步的解释,请参阅 FAQ 条目 如何创建多维列表?。
如果 *i* 或 *j* 为负数,则索引相对于序列 *s* 的末尾:用
len(s) + i
或len(s) + j
替换。但请注意-0
仍然是0
。*i* 到 *j* 的 *s* 切片定义为索引为 *k* 的项的序列,其中
i <= k < j
。如果 *i* 或 *j* 大于len(s)
,则使用len(s)
。如果 *i* 被省略或为None
,则使用0
。如果 *j* 被省略或为None
,则使用len(s)
。如果 *i* 大于或等于 *j*,则切片为空。步长为 *k* 的从 *i* 到 *j* 的 *s* 切片定义为索引为
x = i + n*k
的项的序列,其中0 <= n < (j-i)/k
。换句话说,索引是i
,i+k
,i+2*k
,i+3*k
等等,直到达到 *j*(但永远不包括 *j*)。当 *k* 为正数时,如果 *i* 和 *j* 大于len(s)
,则将它们减小到len(s)
。当 *k* 为负数时,如果 *i* 和 *j* 大于len(s) - 1
,则将它们减小到len(s) - 1
。如果 *i* 或 *j* 被省略或为None
,它们将变成“结束”值(具体是哪个结束取决于 *k* 的符号)。注意,*k* 不能为零。如果 *k* 为None
,则将其视为1
。连接不可变序列总是会产生一个新对象。这意味着通过重复连接来构建序列将具有总序列长度的二次运行时间成本。要获得线性运行时间成本,您必须切换到以下选项之一
如果连接
str
对象,您可以先构建一个列表,然后在最后使用str.join()
,或者写入一个io.StringIO
实例,并在完成后检索其值。如果连接
bytes
对象,您可以类似地使用bytes.join()
或io.BytesIO
,或者使用bytearray
对象进行就地连接。bytearray
对象是可变的,并且具有有效的预分配机制。对于其他类型,请研究相关的类文档。
某些序列类型(例如
range
)仅支持遵循特定模式的项目序列,因此不支持序列连接或重复。如果 i 超出序列范围,则引发
IndexError
。
序列方法
序列类型还支持以下方法
- sequence.count(value, /)¶
返回 value 在 sequence 中出现的总次数。
- sequence.index(value[, start[, stop])¶
返回 value 在 sequence 中首次出现的索引。
如果 value 在 sequence 中未找到,则引发
ValueError
。start 或 stop 参数允许高效地搜索序列的子部分,从 start 开始,在 stop 结束。这大致相当于
start + sequence[start:stop].index(value)
,只是没有复制任何数据。注意
并非所有序列类型都支持传递 start 和 stop 参数。
不可变序列类型¶
不可变序列类型通常实现的唯一操作是也由可变序列类型实现的操作,即内置 hash()
的支持。
此支持允许不可变序列(例如 tuple
实例)用作 dict
键,并存储在 set
和 frozenset
实例中。
尝试哈希包含不可哈希值的不可变序列将导致 TypeError
。
可变序列类型¶
下表中的操作定义在可变序列类型上。提供了 collections.abc.MutableSequence
ABC,以便更轻松地在自定义序列类型上正确实现这些操作。
在表中,s 是可变序列类型的实例,t 是任何可迭代对象,x 是满足 s 施加的任何类型和值限制的任意对象(例如,bytearray
只接受满足 0 <= x <= 255
值限制的整数)。
操作 |
结果 |
备注 |
---|---|---|
|
s 的项 i 被 x 替换 |
|
|
删除 s 的项 i |
|
|
i 到 j 的 s 的切片被可迭代对象 t 的内容替换 |
|
|
从列表中删除 |
|
|
i:j:k 的 s 的元素被 t 的元素替换 |
(1) |
|
删除列表中 |
|
|
用 t 的内容扩展 s(在大多数情况下与 |
|
|
用重复 n 次的内容更新 s |
(2) |
备注
如果 k 不等于
1
,则 t 必须具有与它所替换的切片相同的长度。值 n 是整数,或实现了
__index__()
的对象。 n 的零和负值会清空序列。序列中的项不会被复制;它们被多次引用,如 常用序列操作 中对s * n
的解释。
可变序列方法
可变序列类型还支持以下方法
- sequence.append(value, /)¶
将 value 追加到序列末尾。这相当于编写
seq[len(seq):len(seq)] = [value]
。
- sequence.clear()¶
在 3.3 版本加入。
删除 sequence 中的所有项。这相当于编写
del sequence[:]
。
- sequence.copy()¶
在 3.3 版本加入。
创建序列的浅拷贝。这相当于编写
sequence[:]
。提示
copy()
方法不是MutableSequence
ABC
的一部分,但大多数具体的MutableSequence
类型都提供了它。
- sequence.extend(iterable, /)¶
用 iterable 的内容扩展 sequence。在大多数情况下,这与编写
seq[len(seq):len(seq)] = iterable
相同。
- sequence.insert(index, value, /)¶
在给定 index 处将 value 插入 sequence。这相当于编写
sequence[index:index] = [value]
。
- sequence.pop(index=-1, /)¶
检索 index 处的项,并将其从 sequence 中移除。默认情况下,删除并返回 sequence 中的最后一项。
- sequence.remove(value, /)¶
删除 sequence 中第一个满足
sequence[i] == value
的项。如果 value 在 sequence 中未找到,则引发
ValueError
。
- sequence.reverse()¶
就地反转 sequence 的项。此方法在反转大型序列时保持空间经济性。为了提醒用户它通过副作用操作,它返回
None
。
列表¶
列表是可变序列,通常用于存储同质项的集合(其中同质的程度将因应用程序而异)。
- class list(iterable=(), /)¶
列表可以通过几种方式构建
使用一对方括号表示空列表:
[]
使用方括号,用逗号分隔项:
[a]
,[a, b, c]
使用列表推导式:
[x for x in iterable]
使用类型构造函数:
list()
或list(iterable)
构造函数构建一个列表,其项与 iterable 的项相同且顺序相同。 iterable 可以是序列、支持迭代的容器或迭代器对象。如果 iterable 已经是列表,则会复制并返回该列表,类似于
iterable[:]
。例如,list('abc')
返回['a', 'b', 'c']
,而list( (1, 2, 3) )
返回[1, 2, 3]
。如果未提供参数,则构造函数创建一个新的空列表,[]
。许多其他操作也会产生列表,包括内置的
sorted()
。列表实现了所有 常用 和 可变 序列操作。列表还提供以下附加方法
- sort(*, key=None, reverse=False)¶
此方法就地对列表进行排序,仅使用项之间的
<
比较。不抑制异常——如果任何比较操作失败,则整个排序操作将失败(并且列表可能会处于部分修改状态)。sort()
接受两个只能通过关键字传递的参数(关键字参数)key 指定一个接受一个参数的函数,该函数用于从每个列表元素中提取比较键(例如,
key=str.lower
)。为列表中的每个项计算的键会计算一次,然后用于整个排序过程。默认值None
表示列表项直接排序,而无需计算单独的键值。functools.cmp_to_key()
工具可用于将 2.x 风格的 cmp 函数转换为 key 函数。reverse 是一个布尔值。如果设置为
True
,则列表元素的排序方式就像每个比较都反转了一样。此方法就地修改序列,以便在对大型序列进行排序时节省空间。为了提醒用户它通过副作用操作,它不返回已排序的序列(使用
sorted()
来显式请求新的已排序列表实例)。sort()
方法保证是稳定的。排序是稳定的,如果它保证不改变相等比较的元素之间的相对顺序——这对于多遍排序很有用(例如,先按部门排序,再按薪资等级排序)。有关排序示例和简短的排序教程,请参阅排序技术。
CPython 实现细节: 在对列表进行排序时,尝试修改甚至检查列表的效果是未定义的。Python 的 C 实现会在排序期间使列表看起来为空,并且如果它检测到列表在排序期间被修改,则会引发
ValueError
。
元组¶
元组是不可变序列,通常用于存储异构数据集合(例如 enumerate()
内置函数生成的 2 元组)。元组也用于需要同质数据不可变序列的情况(例如,允许存储在 set
或 dict
实例中)。
- class tuple(iterable=(), /)¶
元组可以通过多种方式构建
使用一对括号表示空元组:
()
使用尾随逗号表示单个元组:
a,
或(a,)
用逗号分隔项:
a, b, c
或(a, b, c)
使用
tuple()
内置函数:tuple()
或tuple(iterable)
构造函数构建一个元组,其项与 iterable 的项相同且顺序相同。 iterable 可以是序列、支持迭代的容器或迭代器对象。如果 iterable 已经是元组,则原样返回。例如,
tuple('abc')
返回('a', 'b', 'c')
,而tuple( [1, 2, 3] )
返回(1, 2, 3)
。如果未提供参数,则构造函数创建一个新的空元组,()
。请注意,使元组成为元组的实际上是逗号,而不是括号。括号是可选的,除非在空元组的情况下,或者当它们需要避免语法歧义时。例如,
f(a, b, c)
是一个有三个参数的函数调用,而f((a, b, c))
是一个以 3 元组作为唯一参数的函数调用。元组实现了所有 常用 序列操作。
对于数据异构集合,其中按名称访问比按索引访问更清晰,collections.namedtuple()
可能比简单的元组对象更合适。
范围¶
range
类型表示一个不可变的数字序列,通常用于在 for
循环中循环特定次数。
- class range(stop, /)¶
- class range(start, stop, step=1, /)
范围构造函数的参数必须是整数(可以是内置的
int
或任何实现了__index__()
特殊方法的对象)。如果省略 step 参数,则默认为1
。如果省略 start 参数,则默认为0
。如果 step 为零,则引发ValueError
。对于正 step,范围
r
的内容由公式r[i] = start + step*i
确定,其中i >= 0
且r[i] < stop
。对于负 step,范围的内容仍由公式
r[i] = start + step*i
确定,但约束条件是i >= 0
且r[i] > stop
。如果
r[0]
不满足值约束,则范围对象将为空。范围确实支持负索引,但这些索引被解释为从由正索引确定的序列末尾开始索引。允许包含绝对值大于
sys.maxsize
的范围,但某些功能(例如len()
)可能会引发OverflowError
。范围示例
>>> list(range(10)) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> list(range(1, 11)) [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] >>> list(range(0, 30, 5)) [0, 5, 10, 15, 20, 25] >>> list(range(0, 10, 3)) [0, 3, 6, 9] >>> list(range(0, -10, -1)) [0, -1, -2, -3, -4, -5, -6, -7, -8, -9] >>> list(range(0)) [] >>> list(range(1, 0)) []
范围实现了所有 常用 序列操作,但不支持连接和重复(因为范围对象只能表示遵循严格模式的序列,而重复和连接通常会违反该模式)。
- start¶
start 参数的值(如果未提供该参数,则为
0
)
- stop¶
stop 参数的值
- step¶
step 参数的值(如果未提供该参数,则为
1
)
range
类型相对于普通 list
或 tuple
的优点是,range
对象占用的内存量始终相同(很小),而不管它表示的范围大小(因为它只存储 start
、stop
和 step
值,并按需计算单个项和子范围)。
范围对象实现了 collections.abc.Sequence
ABC,并提供成员测试、元素索引查找、切片和负索引支持等功能(请参阅 序列类型 — list, tuple, range)。
>>> r = range(0, 20, 2)
>>> r
range(0, 20, 2)
>>> 11 in r
False
>>> 10 in r
True
>>> r.index(10)
5
>>> r[5]
10
>>> r[:5]
range(0, 10, 2)
>>> r[-1]
18
使用 ==
和 !=
测试范围对象的相等性会将其作为序列进行比较。也就是说,如果两个范围对象代表相同的数值序列,则它们被视为相等。(请注意,两个相等的范围对象可能具有不同的 start
、stop
和 step
属性,例如 range(0) == range(2, 1, 3)
或 range(0, 3, 2) == range(0, 4, 2)
。)
3.2 版更改: 实现 Sequence ABC。支持切片和负索引。以恒定时间测试 int
对象是否为成员,而不是迭代所有项。
参见
linspace recipe 展示了如何实现适合浮点应用程序的惰性范围版本。
文本和二进制序列类型方法摘要¶
下表按类别总结了文本和二进制序列类型的各种方法。
类别 |
|
|||||||
---|---|---|---|---|---|---|---|---|
格式化 |
||||||||
搜索和替换 |
||||||||
拆分和连接 |
||||||||
字符串分类 |
||||||||
大小写转换 |
||||||||
填充和去除 |
||||||||
转换和编码 |
||||||||
文本序列类型 — str
¶
Python 中的文本数据使用 str
对象,即字符串来处理。字符串是 Unicode code point 的不可变序列。字符串字面量有多种写法
单引号:
'allows embedded "double" quotes'
双引号:
"allows embedded 'single' quotes"
三引号:
'''Three single quotes'''
,"""Three double quotes"""
三引号字符串可以跨越多行——所有相关的空格都将包含在字符串字面量中。
位于单个表达式中且之间只有空格的字符串字面量将被隐式转换为单个字符串字面量。也就是说,("spam " "eggs") == "spam eggs"
。
有关字符串字面量的各种形式,包括支持的转义序列,以及禁用大多数转义序列处理的 r
(“原始”)前缀,请参阅 字符串和字节字面量。
还可以使用 str
构造函数从其他对象创建字符串。
由于没有单独的“字符”类型,因此对字符串进行索引会产生长度为 1 的字符串。也就是说,对于非空字符串 s,s[0] == s[0:1]
。
也没有可变的字符串类型,但是 str.join()
或 io.StringIO
可用于高效地从多个片段构建字符串。
3.3 版更改: 为了与 Python 2 系列向后兼容,字符串字面量再次允许使用 u
前缀。它对字符串字面量的含义没有影响,也不能与 r
前缀结合使用。
- class str(*, encoding='utf-8', errors='strict')¶
- class str(object)
- class str(object, encoding, errors='strict')
- class str(object, *, errors)
返回 object 的字符串版本。如果未提供 object,则返回空字符串。否则,
str()
的行为取决于是否给出了 encoding 或 errors,如下所示。如果未提供 encoding 和 errors,则
str(object)
返回type(object).__str__(object)
,这是 object 的“非正式”或易于打印的字符串表示形式。对于字符串对象,这是字符串本身。如果 object 没有__str__()
方法,则str()
会回退到返回repr(object)
。如果至少给出了 encoding 或 errors 中的一个,则 object 应该是类字节对象(例如
bytes
或bytearray
)。在这种情况下,如果 object 是bytes
(或bytearray
)对象,则str(bytes, encoding, errors)
等同于bytes.decode(encoding, errors)
。否则,在调用bytes.decode()
之前会获取缓冲区对象下面的字节对象。有关缓冲区对象的信息,请参阅 二进制序列类型 — bytes, bytearray, memoryview 和 缓冲区协议。在没有 encoding 或 errors 参数的情况下将
bytes
对象传递给str()
属于第一种情况,返回非正式字符串表示(另请参阅 Python 命令行选项-b
)。例如>>> str(b'Zoot!') "b'Zoot!'"
有关
str
类及其方法的更多信息,请参阅 文本序列类型 — str 和下面的 字符串方法 部分。要输出格式化字符串,请参阅 f-strings 和 格式字符串语法 部分。此外,请参阅 文本处理服务 部分。
字符串方法¶
字符串实现了所有 常用 序列操作,以及下面描述的附加方法。
字符串还支持两种字符串格式化风格,一种提供了高度的灵活性和可定制性(请参阅 str.format()
、格式字符串语法 和 自定义字符串格式化),另一种基于 C printf
风格格式化,它处理的类型范围较窄,并且稍微难以正确使用,但对于它能处理的情况通常速度更快(printf 风格字符串格式化)。
文本处理服务 部分的标准库涵盖了许多提供各种文本相关实用程序的模块(包括 re
模块中的正则表达式支持)。
- str.capitalize()¶
返回字符串的副本,其中第一个字符大写,其余字符小写。
3.8 版更改: 第一个字符现在被转换为首字母大写而不是大写。这意味着像二合字母这样的字符只会将第一个字母大写,而不是整个字符。
- str.casefold()¶
返回字符串的折叠大小写版本。折叠大小写的字符串可用于不区分大小写的匹配。
折叠大小写类似于小写,但更具侵略性,因为它旨在删除字符串中的所有大小写差异。例如,德语小写字母
'ß'
等同于"ss"
。由于它已经是小写,lower()
对'ß'
不会有任何操作;casefold()
将其转换为"ss"
。折叠大小写算法在《Unicode 标准》第 3.13 节“默认大小写折叠”中进行了描述。
在 3.3 版本加入。
- str.center(width, fillchar=' ', /)¶
返回长度为 width 的居中字符串。填充使用指定的 fillchar(默认为 ASCII 空格)。如果 width 小于或等于
len(s)
,则返回原始字符串。例如>>> 'Python'.center(10) ' Python ' >>> 'Python'.center(10, '-') '--Python--' >>> 'Python'.center(4) 'Python'
- str.count(sub[, start[, end]])¶
返回子字符串 sub 在范围 [start, end] 中非重叠出现的次数。可选参数 start 和 end 按切片表示法解释。
如果 sub 为空,则返回字符之间空字符串的数量,即字符串长度加一。例如
>>> 'spam, spam, spam'.count('spam') 3 >>> 'spam, spam, spam'.count('spam', 5) 2 >>> 'spam, spam, spam'.count('spam', 5, 10) 1 >>> 'spam, spam, spam'.count('eggs') 0 >>> 'spam, spam, spam'.count('') 17
- str.encode(encoding='utf-8', errors='strict')¶
返回编码为
bytes
的字符串。encoding 默认为
'utf-8'
;有关可能的值,请参阅 标准编码。errors 控制如何处理编码错误。如果为
'strict'
(默认),则引发UnicodeError
异常。其他可能的值包括'ignore'
、'replace'
、'xmlcharrefreplace'
、'backslashreplace'
以及通过codecs.register_error()
注册的任何其他名称。有关详细信息,请参阅 错误处理程序。出于性能原因,errors 的值不会在实际发生编码错误、Python 开发模式 启用或使用调试构建 时进行有效性检查。例如
>>> encoded_str_to_bytes = 'Python'.encode() >>> type(encoded_str_to_bytes) <class 'bytes'> >>> encoded_str_to_bytes b'Python'
3.1 版更改: 添加了对关键字参数的支持。
3.9 版更改: errors 参数的值现在在 Python 开发模式 和 调试模式 下进行检查。
- str.endswith(suffix[, start[, end]])¶
如果字符串以指定的 suffix 结尾,则返回
True
,否则返回False
。suffix 也可以是要查找的后缀元组。使用可选的 start,从该位置开始测试。使用可选的 end,在此位置停止比较。使用 start 和 end 相当于str[start:end].endswith(suffix)
。例如>>> 'Python'.endswith('on') True >>> 'a tuple of suffixes'.endswith(('at', 'in')) False >>> 'a tuple of suffixes'.endswith(('at', 'es')) True >>> 'Python is amazing'.endswith('is', 0, 9) True
另请参阅
startswith()
和removesuffix()
。
- str.expandtabs(tabsize=8)¶
返回字符串的副本,其中所有制表符都被替换为一个或多个空格,具体取决于当前列和给定的制表符大小。制表符位置每 tabsize 个字符出现一次(默认为 8,制表符位置在列 0、8、16 等处)。要展开字符串,当前列设置为零,字符串逐个字符进行检查。如果字符是制表符(
\t
),则在结果中插入一个或多个空格字符,直到当前列等于下一个制表符位置。(制表符本身不复制。)如果字符是换行符(\n
)或回车符(\r
),则复制该字符,并将当前列重置为零。任何其他字符都按原样复制,并且当前列增加一,而不考虑字符打印时的表示方式。例如>>> '01\t012\t0123\t01234'.expandtabs() '01 012 0123 01234' >>> '01\t012\t0123\t01234'.expandtabs(4) '01 012 0123 01234' >>> print('01\t012\n0123\t01234'.expandtabs(4)) 01 012 0123 01234
- str.find(sub[, start[, end]])¶
返回子字符串 sub 在切片
s[start:end]
中首次出现的最低索引。可选参数 start 和 end 按切片表示法解释。如果未找到 sub,则返回-1
。例如>>> 'spam, spam, spam'.find('sp') 0 >>> 'spam, spam, spam'.find('sp', 5) 6
- str.format(*args, **kwargs)¶
执行字符串格式化操作。调用此方法的字符串可以包含字面文本或由花括号
{}
分隔的替换字段。每个替换字段包含位置参数的数字索引,或关键字参数的名称。返回字符串的副本,其中每个替换字段都替换为相应参数的字符串值。>>> "The sum of 1 + 2 is {0}".format(1+2) 'The sum of 1 + 2 is 3'
有关可以在格式字符串中指定的各种格式选项的说明,请参阅 格式字符串语法。
备注
当使用
n
类型格式化数字(int
、float
、complex
、decimal.Decimal
和子类)时(例如,'{:n}'.format(1234)
),该函数会临时将LC_CTYPE
区域设置为LC_NUMERIC
区域,以解码localeconv()
的decimal_point
和thousands_sep
字段(如果它们是非 ASCII 或长度超过 1 字节),并且LC_NUMERIC
区域与LC_CTYPE
区域不同。此临时更改会影响其他线程。3.7 版更改: 当使用
n
类型格式化数字时,该函数在某些情况下会临时将LC_CTYPE
区域设置为LC_NUMERIC
区域。
- str.format_map(mapping, /)¶
类似于
str.format(**mapping)
,但mapping
直接使用而不复制到dict
。这在例如mapping
是 dict 子类时很有用。>>> class Default(dict): ... def __missing__(self, key): ... return key ... >>> '{name} was born in {country}'.format_map(Default(name='Guido')) 'Guido was born in country'
在 3.2 版本加入。
- str.index(sub[, start[, end]])¶
与
find()
类似,但在找不到子字符串时引发ValueError
。
- str.isalnum()¶
如果字符串中的所有字符都是字母数字并且至少有一个字符,则返回
True
,否则返回False
。字符c
是字母数字的,如果以下任一返回True
:c.isalpha()
、c.isdecimal()
、c.isdigit()
或c.isnumeric()
。
- str.isalpha()¶
如果字符串中的所有字符都是字母并且至少有一个字符,则返回
True
,否则返回False
。字母字符是 Unicode 字符数据库中定义为“Letter”的字符,即具有通用类别属性为“Lm”、“Lt”、“Lu”、“Ll”或“Lo”之一的字符。请注意,这与《Unicode 标准》第 4.10 节“字母、字母和表意字符”中定义的字母属性不同。
- str.isascii()¶
如果字符串为空或字符串中的所有字符都是 ASCII 字符,则返回
True
,否则返回False
。ASCII 字符的代码点在 U+0000-U+007F 范围内。在 3.7 版本加入。
- str.isdecimal()¶
如果字符串中的所有字符都是十进制字符并且至少有一个字符,则返回
True
,否则返回False
。十进制字符是可用于形成十进制数的字符,例如 U+0660、阿拉伯-印度数字零。形式上,十进制字符是 Unicode 通用类别“Nd”中的字符。
- str.isdigit()¶
如果字符串中的所有字符都是数字,并且至少有一个字符,则返回
True
,否则返回False
。数字包括十进制字符和需要特殊处理的数字,例如兼容的上标数字。这包括不能用于构成十进制数字的数字,如迦罗什文字数字。形式上,数字是具有属性值Numeric_Type=Digit
或Numeric_Type=Decimal
的字符。
- str.isidentifier()¶
如果字符串是有效的标识符(根据语言定义,请参阅名称(标识符和关键字)部分),则返回
True
。可以使用
keyword.iskeyword()
来测试字符串s
是否为保留标识符,例如def
和class
。示例
>>> from keyword import iskeyword >>> 'hello'.isidentifier(), iskeyword('hello') (True, False) >>> 'def'.isidentifier(), iskeyword('def') (True, True)
- str.isnumeric()¶
如果字符串中的所有字符都是数字字符,并且至少有一个字符,则返回
True
,否则返回False
。数字字符包括数字字符以及具有 Unicode 数字值属性的所有字符,例如 U+2155, VULGAR FRACTION ONE FIFTH。形式上,数字字符是那些属性值为Numeric_Type=Digit
,Numeric_Type=Decimal
或Numeric_Type=Numeric
的字符。
- str.isprintable()¶
如果字符串中的所有字符都是可打印字符,则返回
True
;如果字符串包含至少一个不可打印字符,则返回False
。这里的“可打印”是指该字符适合
repr()
用于其输出;“不可打印”是指repr()
对内置类型会对其进行十六进制转义。这不影响写入sys.stdout
或sys.stderr
的字符串的处理。可打印字符是指在 Unicode 字符数据库(请参阅
unicodedata
)中,其常规类别属于字母(Letter)、标记(Mark)、数字(Number)、标点(Punctuation)或符号(Symbol)组(L、M、N、P 或 S);再加上 ASCII 空格 0x20。不可打印字符是指属于分隔符(Separator)或其它(Other)组(Z 或 C)的字符,但不包括 ASCII 空格。
- str.isspace()¶
如果字符串中只有空白字符并且至少有一个字符,则返回
True
,否则返回False
。一个字符是空白字符,如果在 Unicode 字符数据库(请参阅
unicodedata
)中,其常规类别是'Zs'
(“分隔符,空格”),或者其双向类是'WS'
、'B'
或'S'
之一。
- str.istitle()¶
如果字符串是标题化的字符串并且至少有一个字符(例如,大写字符只能跟在非大小写字符后面,小写字符只能跟在大小写字符后面),则返回
True
。否则返回False
。例如:
>>> 'Spam, Spam, Spam'.istitle() True >>> 'spam, spam, spam'.istitle() False >>> 'SPAM, SPAM, SPAM'.istitle() False
另请参阅
title()
。
- str.isupper()¶
如果字符串中的所有可区分大小写的字符[4]均为大写,并且至少有一个可区分大小写的字符,则返回
True
,否则返回False
。>>> 'BANANA'.isupper() True >>> 'banana'.isupper() False >>> 'baNana'.isupper() False >>> ' '.isupper() False
- str.join(iterable, /)¶
返回一个字符串,该字符串是iterable中字符串的连接。如果iterable中有任何非字符串值(包括
bytes
对象),则将引发TypeError
。元素之间的分隔符是提供此方法的字符串。
- str.ljust(width, fillchar=' ', /)¶
返回一个长度为width的字符串,其中字符串左对齐。填充使用指定的fillchar(默认为ASCII空格)。如果width小于或等于
len(s)
,则返回原始字符串。
- str.lstrip(chars=None, /)¶
返回字符串的一个副本,其中删除前导字符。chars 参数是一个指定要删除的字符集的字符串。如果省略或为
None
,则chars 参数默认为删除空白字符。chars 参数不是前缀;而是,其值的所有组合都会被剥离。>>> ' spacious '.lstrip() 'spacious ' >>> 'www.example.com'.lstrip('cmowz.') 'example.com'
请参阅
str.removeprefix()
方法,该方法将删除单个前缀字符串而不是所有字符集。例如>>> 'Arthur: three!'.lstrip('Arthur: ') 'ee!' >>> 'Arthur: three!'.removeprefix('Arthur: ') 'three!'
- static str.maketrans(dict, /)¶
- static str.maketrans(from, to, remove='', /)
此静态方法返回一个可用于
str.translate()
的翻译表。如果只有一个参数,则它必须是一个字典,将 Unicode 序数(整数)或字符(长度为 1 的字符串)映射到 Unicode 序数、字符串(任意长度)或
None
。字符键随后将被转换为序数。如果有两个参数,它们必须是等长的字符串,并且在生成的字典中,from中的每个字符将映射到to中相同位置的字符。如果存在第三个参数,则它必须是一个字符串,该字符串中的字符将被映射到结果中的
None
。
- str.partition(sep, /)¶
在第一次出现sep时分割字符串,并返回一个包含分隔符之前的部分、分隔符本身以及分隔符之后的部分的 3 元组。如果找不到分隔符,则返回一个包含字符串本身,后跟两个空字符串的 3 元组。
- str.removeprefix(prefix, /)¶
如果字符串以prefix字符串开头,则返回
string[len(prefix):]
。否则,返回原始字符串的副本。>>> 'TestHook'.removeprefix('Test') 'Hook' >>> 'BaseTestCase'.removeprefix('Test') 'BaseTestCase'
在 3.9 版本中新增。
- str.removesuffix(suffix, /)¶
如果字符串以suffix字符串结尾且suffix不为空,则返回
string[:-len(suffix)]
。否则,返回原始字符串的副本。>>> 'MiscTests'.removesuffix('Tests') 'Misc' >>> 'TmpDirMixin'.removesuffix('Tests') 'TmpDirMixin'
在 3.9 版本中新增。
- str.replace(old, new, /, count=-1)¶
返回字符串的副本,其中所有出现的子字符串old都被替换为new。如果给出了count,则只替换前count个出现。如果未指定count或为
-1
,则替换所有出现。版本 3.13 中已更改: count现在可以作为关键字参数支持。
- str.rfind(sub[, start[, end]])¶
返回字符串中子字符串sub出现处的最高索引,使得sub包含在
s[start:end]
内。可选参数start和end的解释方式与切片表示法相同。失败时返回-1
。
- str.rindex(sub[, start[, end]])¶
与
rfind()
类似,但在找不到子字符串sub时引发ValueError
。
- str.rjust(width, fillchar=' ', /)¶
返回一个长度为width的字符串,其中字符串右对齐。填充使用指定的fillchar(默认为ASCII空格)。如果width小于或等于
len(s)
,则返回原始字符串。
- str.rpartition(sep, /)¶
在最后一次出现sep时分割字符串,并返回一个包含分隔符之前的部分、分隔符本身以及分隔符之后的部分的 3 元组。如果找不到分隔符,则返回一个包含两个空字符串,后跟字符串本身的 3 元组。
- str.rsplit(sep=None, maxsplit=-1)¶
返回字符串中单词的列表,使用sep作为分隔符字符串。如果给出了maxsplit,则最多进行maxsplit次分割,即最右边的分割。如果未指定sep或为
None
,则任何空白字符串都是分隔符。除了从右侧分割之外,rsplit()
的行为与下面详细介绍的split()
相同。
- str.rstrip(chars=None, /)¶
返回字符串的一个副本,其中删除尾随字符。chars 参数是一个指定要删除的字符集的字符串。如果省略或为
None
,则chars 参数默认为删除空白字符。chars 参数不是后缀;而是,其值的所有组合都会被剥离。>>> ' spacious '.rstrip() ' spacious' >>> 'mississippi'.rstrip('ipz') 'mississ'
请参阅
str.removesuffix()
方法,该方法将删除单个后缀字符串而不是所有字符集。例如>>> 'Monty Python'.rstrip(' Python') 'M' >>> 'Monty Python'.removesuffix(' Python') 'Monty'
- str.split(sep=None, maxsplit=-1)¶
返回字符串中单词的列表,使用sep作为分隔符字符串。如果给出了maxsplit,则最多进行maxsplit次分割(因此,列表最多包含
maxsplit+1
个元素)。如果未指定maxsplit或为-1
,则对分割次数没有限制(进行所有可能的分割)。如果给出了sep,则连续的分隔符不会被分组在一起,并被视为分隔空字符串(例如,
'1,,2'.split(',')
返回['1', '', '2']
)。sep参数可以包含多个字符作为一个分隔符(要使用多个分隔符进行分割,请使用re.split()
)。分割空字符串时,如果指定了分隔符,则返回['']
。例如:
>>> '1,2,3'.split(',') ['1', '2', '3'] >>> '1,2,3'.split(',', maxsplit=1) ['1', '2,3'] >>> '1,2,,3,'.split(',') ['1', '2', '', '3', ''] >>> '1<>2<>3<4'.split('<>') ['1', '2', '3<4']
如果未指定sep或为
None
,则应用不同的分割算法:连续的空白字符被视为单个分隔符,并且结果不包含开头或结尾的空字符串(如果字符串有前导或尾随空白)。因此,使用None
分隔符分割空字符串或仅包含空白字符的字符串将返回[]
。例如:
>>> '1 2 3'.split() ['1', '2', '3'] >>> '1 2 3'.split(maxsplit=1) ['1', '2 3'] >>> ' 1 2 3 '.split() ['1', '2', '3']
如果未指定sep或为
None
且maxsplit为0
,则仅考虑前导的连续空白字符。例如:
>>> "".split(None, 0) [] >>> " ".split(None, 0) [] >>> " foo ".split(maxsplit=0) ['foo ']
- str.splitlines(keepends=False)¶
返回字符串中行的列表,按行边界断开。除非指定了keepends且其值为真,否则行边界不会包含在生成的列表中。
此方法根据以下行边界进行分割。特别是,这些边界是通用换行符的超集。
表示
描述
\n
换行符
\r
回车符
\r\n
回车符+换行符
\v
或\x0b
垂直制表符
\f
或\x0c
换页符
\x1c
文件分隔符
\x1d
组分隔符
\x1e
记录分隔符
\x85
换行(C1 控制码)
\u2028
行分隔符
\u2029
段落分隔符
版本 3.2 中已更改:
\v
和\f
已添加到行边界列表中。例如:
>>> 'ab c\n\nde fg\rkl\r\n'.splitlines() ['ab c', '', 'de fg', 'kl'] >>> 'ab c\n\nde fg\rkl\r\n'.splitlines(keepends=True) ['ab c\n', '\n', 'de fg\r', 'kl\r\n']
与给定分隔符字符串sep的
split()
不同,此方法对于空字符串返回一个空列表,并且末尾的换行符不会产生额外的行。>>> "".splitlines() [] >>> "One line\n".splitlines() ['One line']
作为比较,
split('\n')
的结果是>>> ''.split('\n') [''] >>> 'Two lines\n'.split('\n') ['Two lines', '']
- str.startswith(prefix[, start[, end]])¶
如果字符串以prefix开头,则返回
True
,否则返回False
。prefix也可以是用于搜索的前缀元组。使用可选的start,从该位置开始测试字符串。使用可选的end,在此位置停止比较字符串。
- str.strip(chars=None, /)¶
返回字符串的一个副本,其中删除前导和尾随字符。chars 参数是一个指定要删除的字符集的字符串。如果省略或为
None
,则chars 参数默认为删除空白字符。chars 参数不是前缀或后缀;而是,其值的所有组合都会被剥离。>>> ' spacious '.strip() 'spacious' >>> 'www.example.com'.strip('cmowz.') 'example'
最外层的前导和尾随chars参数值将从字符串中剥离。字符会从前导末尾开始删除,直到遇到字符串中不包含在chars字符集中的字符。类似的操作会在尾随末尾进行。例如
>>> comment_string = '#....... Section 3.2.1 Issue #32 .......' >>> comment_string.strip('.#! ') 'Section 3.2.1 Issue #32'
- str.swapcase()¶
返回字符串的一个副本,其中大写字符转换为小写,反之亦然。请注意,
s.swapcase().swapcase() == s
并不总是成立。
- str.title()¶
返回字符串的标题化版本,其中单词以大写字母开头,其余字符为小写。
例如:
>>> 'Hello world'.title() 'Hello World'
该算法使用一种简单的、与语言无关的单词定义,即将单词定义为连续字母的组。该定义在许多情况下都有效,但这意味着缩写和所有格中的撇号会形成单词边界,这可能不是期望的结果。
>>> "they're bill's friends from the UK".title() "They'Re Bill'S Friends From The Uk"
string.capwords()
函数没有这个问题,因为它只按空格分割单词。或者,可以使用正则表达式来解决撇号的问题。
>>> import re >>> def titlecase(s): ... return re.sub(r"[A-Za-z]+('[A-Za-z]+)?", ... lambda mo: mo.group(0).capitalize(), ... s) ... >>> titlecase("they're bill's friends.") "They're Bill's Friends."
另请参阅
istitle()
。
- str.translate(table, /)¶
返回字符串的副本,其中每个字符都已通过指定的翻译表进行映射。该表必须是一个通过
__getitem__()
实现索引的对象,通常是映射或序列。当通过 Unicode 序数(整数)进行索引时,该表对象可以执行以下任何操作:返回一个 Unicode 序数或字符串,将字符映射到一个或多个其他字符;返回None
,将字符从返回字符串中删除;或者引发LookupError
异常,将字符映射到其自身。您可以使用
str.maketrans()
从不同格式的字符到字符映射创建翻译映射。另请参阅
codecs
模块,以获得更灵活的自定义字符映射方法。
- str.upper()¶
返回字符串的一个副本,其中所有可区分大小写的字符[4]都转换为大写。请注意,如果
s
包含非大小写字符,或者如果结果字符的 Unicode 类别不是“Lu”(字母,大写),而是例如“Lt”(字母,标题化),则s.upper().isupper()
可能为False
。
- str.zfill(width, /)¶
返回字符串的副本,在左侧填充 ASCII
'0'
数字,使其长度为width。前导符号前缀('+'
/'-'
)的处理方式是将填充符插入在符号字符之后而不是之前。如果width小于或等于len(s)
,则返回原始字符串。例如:
>>> "42".zfill(5) '00042' >>> "-42".zfill(5) '-0042'
格式化字符串字面量(f-string)¶
在 3.6 版本加入。
版本 3.8 中已更改: 添加了调试运算符(=
)。
版本 3.12 中已更改: f-string 中的表达式的许多限制已被移除。特别是,现在允许嵌套字符串、注释和反斜杠。
f-string(形式上是格式化字符串字面量)是以f
或F
为前缀的字符串字面量。这种类型的字符串字面量允许将任意 Python 表达式嵌入到替换字段中,替换字段由花括号({}
)分隔。这些表达式在运行时进行求值,类似于str.format()
,并被转换为常规的str
对象。例如
>>> who = 'nobody'
>>> nationality = 'Spanish'
>>> f'{who.title()} expects the {nationality} Inquisition!'
'Nobody expects the Spanish Inquisition!'
也可以使用多行 f-string。
>>> f'''This is a string
... on two lines'''
'This is a string\non two lines'
单个开花括号'{'
标记一个替换字段,它可以包含任何 Python 表达式。
>>> nationality = 'Spanish'
>>> f'The {nationality} Inquisition!'
'The Spanish Inquisition!'
要包含字面量{
或}
,请使用双括号。
>>> x = 42
>>> f'{{x}} is {x}'
'{x} is 42'
也可以使用函数,以及格式说明符。
>>> from math import sqrt
>>> f'√2 \N{ALMOST EQUAL TO} {sqrt(2):.5f}'
'√2 ≈ 1.41421'
任何非字符串表达式都默认使用str()
进行转换。
>>> from fractions import Fraction
>>> f'{Fraction(1, 3)}'
'1/3'
要使用显式转换,请使用!
(感叹号)运算符,后跟任何有效的格式,这些格式是:
转换 |
含义 |
---|---|
|
|
|
|
|
例如:
>>> from fractions import Fraction
>>> f'{Fraction(1, 3)!s}'
'1/3'
>>> f'{Fraction(1, 3)!r}'
'Fraction(1, 3)'
>>> question = '¿Dónde está el Presidente?'
>>> print(f'{question!a}')
'\xbfD\xf3nde est\xe1 el Presidente?'
在调试时,通过使用等号(=
)跟在表达式后面,可以同时查看表达式及其值。这会保留方括号内的空格,并可与转换器一起使用。默认情况下,调试运算符使用repr()
(!r
)转换。例如
>>> from fractions import Fraction
>>> calculation = Fraction(1, 3)
>>> f'{calculation=}'
'calculation=Fraction(1, 3)'
>>> f'{calculation = }'
'calculation = Fraction(1, 3)'
>>> f'{calculation = !s}'
'calculation = 1/3'
一旦输出了求值,就可以使用冒号(':'
)后面的格式说明符对其进行格式化。在表达式求值(可能已转换为字符串)后,会使用格式说明符(如果没有给出格式说明符,则为空字符串)调用结果的__format__()
方法。然后使用格式化结果作为替换字段的最终值。例如
>>> from fractions import Fraction
>>> f'{Fraction(1, 7):.6f}'
'0.142857'
>>> f'{Fraction(1, 7):_^+10}'
'___+1/7___'
`printf`风格的字符串格式化¶
备注
此处描述的格式化操作表现出各种细微差别,导致许多常见错误(例如,无法正确显示元组和字典)。
使用格式化字符串字面量、str.format()
接口或string.Template
可能有助于避免这些错误。这些替代方法中的每一种都提供了各自的权衡和优点,如简洁性、灵活性和/或可扩展性。
字符串对象有一个独特内置操作:%
运算符(模)。这也称为字符串格式化或插值运算符。给定format % values
(其中format是字符串),format中的%
转换规范会被values中的零个或多个项替换。效果类似于 C 语言中的sprintf()
函数。例如
>>> print('%s has %d quote types.' % ('Python', 2))
Python has 2 quote types.
如果format需要单个参数,则values可以是单个非元组对象。[5]否则,values必须是一个元组,其中包含格式字符串指定的项目数,或者是一个单一的映射对象(例如,字典)。
转换规范包含两个或更多个字符,并具有以下组成部分,它们必须按此顺序出现:
标记规范开头的
'%'
字符。映射键(可选),由一系列括号括起来的字符组成(例如,
(somename)
)。转换标志(可选),它们会影响某些转换类型的結果。
最小字段宽度(可选)。如果指定为
'*'
(星号),则实际宽度将从values中的下一个元素读取,要转换的对象将出现在最小字段宽度和可选精度之后。精度(可选),给出为
'.'
(点)后跟精度。如果指定为'*'
(星号),则实际精度将从values中的下一个元素读取,要转换的值将出现在精度之后。长度修改符(可选)。
转换类型。
当右参数是字典(或其他映射类型)时,字符串中的格式必须包括一个紧跟在'%'
字符之后的、指向该字典的括号映射键。映射键从映射中选择要格式化的值。例如
>>> print('%(language)s has %(number)03d quote types.' %
... {'language': "Python", "number": 2})
Python has 002 quote types.
在这种情况下,格式中可能不会出现*
规范(因为它们需要顺序参数列表)。
转换标志字符是:
Flag |
含义 |
---|---|
|
转换将使用“备用形式”(如下定义)。 |
|
对于数字值,转换将使用零填充。 |
|
转换将左对齐(如果两者都给出,则覆盖 |
|
(空格)在有符号转换产生的正数(或空字符串)之前应留有一个空格。 |
|
符号字符( |
长度修改符(h
, l
, 或 L
)可能存在,但在 Python 中被忽略,因为它们不是必需的——所以例如%ld
与%d
相同。
转换类型是:
转换 |
含义 |
备注 |
---|---|---|
|
带符号整数十进制。 |
|
|
带符号整数十进制。 |
|
|
带符号八进制值。 |
(1) |
|
已弃用的类型——它与 |
(6) |
|
带符号十六进制(小写)。 |
(2) |
|
带符号十六进制(大写)。 |
(2) |
|
浮点指数格式(小写)。 |
(3) |
|
浮点指数格式(大写)。 |
(3) |
|
浮点十进制格式。 |
(3) |
|
浮点十进制格式。 |
(3) |
|
浮点格式。当指数小于 -4 或不小于精度时,使用小写指数格式,否则使用十进制格式。 |
(4) |
|
浮点格式。当指数小于 -4 或不小于精度时,使用大写指数格式,否则使用十进制格式。 |
(4) |
|
单个字符(接受整数或单字符字符串)。 |
|
|
字符串(使用 |
(5) |
|
字符串(使用 |
(5) |
|
字符串(使用 |
(5) |
|
不转换参数,结果中产生一个 |
备注
备用形式会在第一个数字之前插入一个前导八进制说明符(
'0o'
)。备用形式会在第一个数字之前插入一个前导
'0x'
或'0X'
(取决于使用的是'x'
还是'X'
格式)。备用形式会导致结果始终包含小数点,即使小数点后面没有数字。
精度决定小数点后的位数,默认为 6。
备用形式会导致结果始终包含小数点,并且尾随零不会像通常那样被删除。
精度决定小数点前后有效数字的位数,默认为 6。
如果精度为
N
,则输出将截断为N
个字符。请参阅PEP 237。
由于 Python 字符串具有显式长度,%s
转换不会假定'\0'
是字符串的结尾。
版本 3.1 中已更改: 绝对值大于 1e50 的数字的%f
转换不再被替换为%g
转换。
二进制序列类型 — bytes
, bytearray
, memoryview
¶
用于处理二进制数据的核心内置类型是bytes
和bytearray
。它们由memoryview
支持,该类使用缓冲区协议访问其他二进制对象的内存,而无需复制。
array
模块支持高效存储基本数据类型,如 32 位整数和 IEEE754 双精度浮点值。
字节对象¶
字节对象是单个字节的不可变序列。由于许多主要的二进制协议都基于 ASCII 文本编码,因此字节对象提供了许多仅在处理 ASCII 兼容数据时才有效的方法,并且在许多其他方面与字符串对象密切相关。
- class bytes(source=b'')¶
- class bytes(source, encoding, errors='strict')
首先,字节字面量的语法与字符串字面量的语法基本相同,只是添加了一个
b
前缀。单引号:
b'still allows embedded "double" quotes'
双引号:
b"still allows embedded 'single' quotes"
三引号:
b'''3 single quotes'''
,b"""3 double quotes"""
字节字面量仅允许 ASCII 字符(无论声明的源代码编码如何)。任何大于 127 的二进制值必须在字节字面量中使用适当的转义序列表示。
与字符串字面量一样,字节字面量也可以使用
r
前缀来禁用转义序列的处理。有关各种字节字面量形式(包括支持的转义序列)的更多信息,请参阅字符串和字节字面量。虽然字节字面量和表示基于 ASCII 文本,但字节对象实际上表现为整数的不可变序列,其中序列中的每个值都受到限制,即
0 <= x < 256
(尝试违反此限制将触发ValueError
)。这样做是特意的,以强调虽然许多二进制格式包含基于 ASCII 的元素并且可以有效地使用一些面向文本的算法进行处理,但这通常不适用于任意二进制数据(盲目地将文本处理算法应用于不兼容 ASCII 的二进制数据格式通常会导致数据损坏)。除了字面量形式之外,还可以通过其他多种方式创建字节对象:
指定长度的零填充字节对象:
bytes(10)
从整数的可迭代对象:
bytes(range(20))
通过缓冲区协议复制现有二进制数据:
bytes(obj)
另请参阅bytes内置函数。
由于 2 个十六进制数字精确对应一个字节,因此十六进制数是描述二进制数据的常用格式。因此,bytes 类型有一个额外的类方法来以该格式读取数据:
- classmethod fromhex(string, /)¶
此
bytes
类方法返回一个字节对象,解码给定的字符串对象。字符串必须包含每个字节两个十六进制数字,并忽略 ASCII 空白。>>> bytes.fromhex('2Ef0 F1f2 ') b'.\xf0\xf1\xf2'
版本 3.7 中已更改:
bytes.fromhex()
现在会跳过字符串中的所有 ASCII 空白,而不仅仅是空格。版本 3.14 中已更改:
bytes.fromhex()
现在接受 ASCIIbytes
和类似字节的对象作为输入。
存在一个反向转换函数,用于将字节对象转换为其十六进制表示。
- hex(*, bytes_per_sep=1)¶
- hex(sep, bytes_per_sep=1)
返回一个字符串对象,其中包含实例中每个字节的两个十六进制数字。
>>> b'\xf0\xf1\xf2'.hex() 'f0f1f2'
如果您想使十六进制字符串更易读,可以指定一个单独的字符分隔符sep参数包含在输出中。默认情况下,此分隔符将包含在每个字节之间。第二个可选bytes_per_sep参数控制间距。正值从右侧计算分隔符位置,负值从左侧计算。
>>> value = b'\xf0\xf1\xf2' >>> value.hex('-') 'f0-f1-f2' >>> value.hex('_', 2) 'f0_f1f2' >>> b'UUDDLRLRAB'.hex(' ', -4) '55554444 4c524c52 4142'
在 3.5 版本加入。
版本 3.8 中已更改:
bytes.hex()
现在支持可选的sep和bytes_per_sep参数,以在十六进制输出的字节之间插入分隔符。
由于字节对象是整数序列(类似于元组),对于字节对象b,b[0]
将是一个整数,而b[0:1]
将是一个长度为 1 的字节对象。(这与文本字符串形成对比,在文本字符串中,索引和切片都会生成长度为 1 的字符串)
字节对象的表示使用字面量格式(b'...'
),因为它通常比例如bytes([46, 46, 46])
更有用。您始终可以使用list(b)
将字节对象转换为整数列表。
字节数组对象¶
- class bytearray(source=b'')¶
- class bytearray(source, encoding, errors='strict')
没有专门的字节数组对象字面量语法,而是始终通过调用构造函数来创建它们:
创建空实例:
bytearray()
使用给定长度创建零填充实例:
bytearray(10)
从整数的可迭代对象:
bytearray(range(20))
通过缓冲区协议复制现有二进制数据:
bytearray(b'Hi!')
由于字节数组对象是可变的,因此它们除了字节和字节数组操作中描述的常用字节和字节数组操作外,还支持可变序列操作。
另请参阅bytearray内置函数。
由于 2 个十六进制数字精确对应一个字节,因此十六进制数是描述二进制数据的常用格式。因此,bytearray 类型有一个额外的类方法来以该格式读取数据:
- classmethod fromhex(string, /)¶
此
bytearray
类方法返回一个 bytearray 对象,解码给定的字符串对象。字符串必须包含每个字节两个十六进制数字,并忽略 ASCII 空白。>>> bytearray.fromhex('2Ef0 F1f2 ') bytearray(b'.\xf0\xf1\xf2')
版本 3.7 中已更改:
bytearray.fromhex()
现在会跳过字符串中的所有 ASCII 空白,而不仅仅是空格。版本 3.14 中已更改:
bytearray.fromhex()
现在接受 ASCIIbytes
和类似字节的对象作为输入。
存在一个反向转换函数,用于将 bytearray 对象转换为其十六进制表示。
- hex(*, bytes_per_sep=1)¶
- hex(sep, bytes_per_sep=1)
返回一个字符串对象,其中包含实例中每个字节的两个十六进制数字。
>>> bytearray(b'\xf0\xf1\xf2').hex() 'f0f1f2'
在 3.5 版本加入。
版本 3.8 中已更改: 与
bytes.hex()
类似,bytearray.hex()
现在支持可选的sep和bytes_per_sep参数,以在十六进制输出的字节之间插入分隔符。
- resize(size, /)¶
将
bytearray
的大小调整为包含size字节。size必须大于或等于 0。如果
bytearray
需要缩小,则超出size的字节将被截断。如果
bytearray
需要增长,则所有新字节,即超出size的字节,都将设置为 null 字节。这等价于:
>>> def resize(ba, size): ... if len(ba) > size: ... del ba[size:] ... else: ... ba += b'\0' * (size - len(ba))
示例:
>>> shrink = bytearray(b'abc') >>> shrink.resize(1) >>> (shrink, len(shrink)) (bytearray(b'a'), 1) >>> grow = bytearray(b'abc') >>> grow.resize(5) >>> (grow, len(grow)) (bytearray(b'abc\x00\x00'), 5)
在 3.14 版本加入。
由于字节数组对象是整数序列(类似于列表),对于字节数组对象b,b[0]
将是一个整数,而b[0:1]
将是一个长度为 1 的字节数组对象。(这与文本字符串形成对比,在文本字符串中,索引和切片都会生成长度为 1 的字符串)
字节数组对象的表示使用字节字面量格式(bytearray(b'...')
),因为它通常比例如bytearray([46, 46, 46])
更有用。您始终可以使用list(b)
将字节数组对象转换为整数列表。
字节和字节数组操作¶
bytes 和 bytearray 对象都支持 通用 序列操作。它们不仅可以与同类型的操作数互操作,还可以与任何 类字节对象 互操作。由于这种灵活性,它们可以在操作中自由混合而不会导致错误。但是,结果的返回类型可能取决于操作数的顺序。
备注
bytes 和 bytearray 对象上的方法不接受字符串作为参数,就像字符串上的方法不接受字节作为参数一样。例如,你必须这样写:
a = "abc"
b = a.replace("a", "f")
与
a = b"abc"
b = a.replace(b"a", b"f")
某些 bytes 和 bytearray 操作假定使用 ASCII 兼容的二进制格式,因此在处理任意二进制数据时应避免使用。这些限制在下面介绍。
备注
使用这些基于 ASCII 的操作来处理非 ASCII 格式存储的二进制数据可能会导致数据损坏。
bytes 和 bytearray 对象上的以下方法可用于处理任意二进制数据。
- bytes.count(sub[, start[, end]])¶
- bytearray.count(sub[, start[, end]])¶
返回子序列 sub 在范围 [start, end] 内非重叠出现的次数。可选参数 start 和 end 的解释方式与切片表示法相同。
要搜索的子序列可以是任何 类字节对象 或 0 到 255 范围内的整数。
如果 sub 为空,则返回字符之间的空切片数,即字节对象长度加一。
版本 3.3 中已更改: 现在也接受 0 到 255 范围内的整数作为子序列。
- bytes.removeprefix(prefix, /)¶
- bytearray.removeprefix(prefix, /)¶
如果二进制数据以 prefix 字符串开头,则返回
bytes[len(prefix):]
。否则,返回原始二进制数据的副本。>>> b'TestHook'.removeprefix(b'Test') b'Hook' >>> b'BaseTestCase'.removeprefix(b'Test') b'BaseTestCase'
prefix 可以是任何 类字节对象。
备注
此方法的 bytearray 版本不会就地操作 - 它始终生成新对象,即使未进行任何更改。
在 3.9 版本中新增。
- bytes.removesuffix(suffix, /)¶
- bytearray.removesuffix(suffix, /)¶
如果二进制数据以 suffix 字符串结尾且该 suffix 非空,则返回
bytes[:-len(suffix)]
。否则,返回原始二进制数据的副本。>>> b'MiscTests'.removesuffix(b'Tests') b'Misc' >>> b'TmpDirMixin'.removesuffix(b'Tests') b'TmpDirMixin'
suffix 可以是任何 类字节对象。
备注
此方法的 bytearray 版本不会就地操作 - 它始终生成新对象,即使未进行任何更改。
在 3.9 版本中新增。
- bytes.decode(encoding='utf-8', errors='strict')¶
- bytearray.decode(encoding='utf-8', errors='strict')¶
将字节解码为
str
。encoding 默认为
'utf-8'
;有关可能的值,请参阅 标准编码。errors 控制如何处理解码错误。如果为
'strict'
(默认值),则会引发UnicodeError
异常。其他可能的值包括'ignore'
、'replace'
,以及通过codecs.register_error()
注册的任何其他名称。有关详细信息,请参阅 错误处理程序。出于性能原因,除非实际发生解码错误,Python 开发模式 已启用或使用了 调试构建,否则 errors 的值不会被检查有效性。
3.1 版更改: 添加了对关键字参数的支持。
3.9 版更改: errors 参数的值现在在 Python 开发模式 和 调试模式 下进行检查。
- bytes.endswith(suffix[, start[, end]])¶
- bytearray.endswith(suffix[, start[, end]])¶
如果二进制数据以指定的 suffix 结尾,则返回
True
,否则返回False
。suffix 也可以是用于查找的后缀元组。使用可选的 start,从该位置开始测试。使用可选的 end,在该位置停止比较。要搜索的后缀可以是任何 类字节对象。
- bytes.find(sub[, start[, end]])¶
- bytearray.find(sub[, start[, end]])¶
返回数据中子序列 sub 第一次出现时的最低索引,使得 sub 包含在切片
s[start:end]
中。可选参数 start 和 end 的解释方式与切片表示法相同。如果找不到 sub,则返回-1
。要搜索的子序列可以是任何 类字节对象 或 0 到 255 范围内的整数。
版本 3.3 中已更改: 现在也接受 0 到 255 范围内的整数作为子序列。
- bytes.index(sub[, start[, end]])¶
- bytearray.index(sub[, start[, end]])¶
与
find()
类似,但在找不到子序列时引发ValueError
。要搜索的子序列可以是任何 类字节对象 或 0 到 255 范围内的整数。
版本 3.3 中已更改: 现在也接受 0 到 255 范围内的整数作为子序列。
- bytes.join(iterable, /)¶
- bytearray.join(iterable, /)¶
返回一个 bytes 或 bytearray 对象,它是 iterable 中二进制数据序列的连接。如果 iterable 中存在任何不是 类字节对象(包括
str
对象)的值,则会引发TypeError
。元素之间的分隔符是提供此方法的 bytes 或 bytearray 对象的内容。
- static bytes.maketrans(from, to, /)¶
- static bytearray.maketrans(from, to, /)¶
此静态方法返回一个可用于
bytes.translate()
的转换表,该表会将 from 中的每个字符映射到 to 中相同位置的字符;from 和 to 都必须是 类字节对象 且长度相同。在 3.1 版本加入。
- bytes.partition(sep, /)¶
- bytearray.partition(sep, /)¶
在第一次出现 sep 的位置拆分序列,并返回一个包含分隔符之前的部分、分隔符本身或其 bytearray 副本以及分隔符之后的部分的 3 元组。如果找不到分隔符,则返回一个包含原始序列副本、后跟两个空 bytes 或 bytearray 对象的 3 元组。
要搜索的分隔符可以是任何 类字节对象。
- bytes.replace(old, new, count=-1, /)¶
- bytearray.replace(old, new, count=-1, /)¶
返回序列的副本,其中所有子序列 old 的出现都被 new 替换。如果给出了可选参数 count,则只替换前 count 次出现。
要搜索的子序列及其替换可以是任何 类字节对象。
备注
此方法的 bytearray 版本不会就地操作 - 它始终生成新对象,即使未进行任何更改。
- bytes.rfind(sub[, start[, end]])¶
- bytearray.rfind(sub[, start[, end]])¶
返回序列中子序列 sub 第一次出现时的最高索引,使得 sub 包含在
s[start:end]
中。可选参数 start 和 end 的解释方式与切片表示法相同。失败时返回-1
。要搜索的子序列可以是任何 类字节对象 或 0 到 255 范围内的整数。
版本 3.3 中已更改: 现在也接受 0 到 255 范围内的整数作为子序列。
- bytes.rindex(sub[, start[, end]])¶
- bytearray.rindex(sub[, start[, end]])¶
与
rfind()
类似,但在找不到子序列 sub 时引发ValueError
。要搜索的子序列可以是任何 类字节对象 或 0 到 255 范围内的整数。
版本 3.3 中已更改: 现在也接受 0 到 255 范围内的整数作为子序列。
- bytes.rpartition(sep, /)¶
- bytearray.rpartition(sep, /)¶
在最后一次出现 sep 的位置拆分序列,并返回一个包含分隔符之前的部分、分隔符本身或其 bytearray 副本以及分隔符之后的部分的 3 元组。如果找不到分隔符,则返回一个包含两个空 bytes 或 bytearray 对象、后跟原始序列副本的 3 元组。
要搜索的分隔符可以是任何 类字节对象。
- bytes.startswith(prefix[, start[, end]])¶
- bytearray.startswith(prefix[, start[, end]])¶
如果二进制数据以指定的 prefix 开头,则返回
True
,否则返回False
。prefix 也可以是用于查找的前缀元组。使用可选的 start,从该位置开始测试。使用可选的 end,在该位置停止比较。要搜索的前缀可以是任何 类字节对象。
- bytes.translate(table, /, delete=b'')¶
- bytearray.translate(table, /, delete=b'')¶
返回 bytes 或 bytearray 对象的副本,其中删除可选参数 delete 中出现的所有字节,并将剩余的字节通过给定的转换表进行映射,该表必须是长度为 256 的 bytes 对象。
您可以使用
bytes.maketrans()
方法创建转换表。将 table 参数设置为
None
以仅删除字符的转换。>>> b'read this short text'.translate(None, b'aeiou') b'rd ths shrt txt'
版本 3.6 中已更改: 现在支持 delete 作为关键字参数。
bytes 和 bytearray 对象上的以下方法具有默认行为,这些行为假定使用 ASCII 兼容的二进制格式,但通过传递适当的参数仍可与任意二进制数据一起使用。请注意,此部分中的所有 bytearray 方法不会就地操作,而是生成新对象。
- bytes.center(width, fillbyte=b' ', /)¶
- bytearray.center(width, fillbyte=b' ', /)¶
返回一个居中于长度为 width 的序列中的对象的副本。填充使用指定的 fillbyte(默认为 ASCII 空格)。对于
bytes
对象,如果 width 小于或等于len(s)
,则返回原始序列。备注
此方法的 bytearray 版本不会就地操作 - 它始终生成新对象,即使未进行任何更改。
- bytes.ljust(width, fillbyte=b' ', /)¶
- bytearray.ljust(width, fillbyte=b' ', /)¶
返回一个左对齐于长度为 width 的序列中的对象的副本。填充使用指定的 fillbyte(默认为 ASCII 空格)。对于
bytes
对象,如果 width 小于或等于len(s)
,则返回原始序列。备注
此方法的 bytearray 版本不会就地操作 - 它始终生成新对象,即使未进行任何更改。
- bytes.lstrip(bytes=None, /)¶
- bytearray.lstrip(bytes=None, /)¶
返回一个副本,其中删除了指定的开头字节。bytes 参数是一个二进制序列,指定要删除的字节值集合。如果省略或为
None
,则 bytes 参数默认为删除 ASCII 空白字符。bytes 参数不是前缀;而是,其所有值的组合都会被删除。>>> b' spacious '.lstrip() b'spacious ' >>> b'www.example.com'.lstrip(b'cmowz.') b'example.com'
要删除的字节值的二进制序列可以是任何 类字节对象。有关删除单个前缀字符串而不是一组字符的方法,请参阅
removeprefix()
。例如:>>> b'Arthur: three!'.lstrip(b'Arthur: ') b'ee!' >>> b'Arthur: three!'.removeprefix(b'Arthur: ') b'three!'
备注
此方法的 bytearray 版本不会就地操作 - 它始终生成新对象,即使未进行任何更改。
- bytes.rjust(width, fillbyte=b' ', /)¶
- bytearray.rjust(width, fillbyte=b' ', /)¶
返回一个右对齐于长度为 width 的序列中的对象的副本。填充使用指定的 fillbyte(默认为 ASCII 空格)。对于
bytes
对象,如果 width 小于或等于len(s)
,则返回原始序列。备注
此方法的 bytearray 版本不会就地操作 - 它始终生成新对象,即使未进行任何更改。
- bytes.rsplit(sep=None, maxsplit=-1)¶
- bytearray.rsplit(sep=None, maxsplit=-1)¶
使用 sep 作为分隔符字符串,将二进制序列拆分为相同类型的子序列。如果给出了 maxsplit,则最多执行 maxsplit 次拆分,即最右边的拆分。如果 sep 未指定或为
None
,则任何仅由 ASCII 空白字符组成的子序列都是分隔符。除了从右侧拆分外,rsplit()
的行为与下面详细描述的split()
相同。
- bytes.rstrip(bytes=None, /)¶
- bytearray.rstrip(bytes=None, /)¶
返回一个副本,其中删除了指定的结尾字节。bytes 参数是一个二进制序列,指定要删除的字节值集合。如果省略或为
None
,则 bytes 参数默认为删除 ASCII 空白字符。bytes 参数不是后缀;而是,其所有值的组合都会被删除。>>> b' spacious '.rstrip() b' spacious' >>> b'mississippi'.rstrip(b'ipz') b'mississ'
要删除的字节值的二进制序列可以是任何 类字节对象。有关删除单个后缀字符串而不是一组字符的方法,请参阅
removesuffix()
。例如:>>> b'Monty Python'.rstrip(b' Python') b'M' >>> b'Monty Python'.removesuffix(b' Python') b'Monty'
备注
此方法的 bytearray 版本不会就地操作 - 它始终生成新对象,即使未进行任何更改。
- bytes.split(sep=None, maxsplit=-1)¶
- bytearray.split(sep=None, maxsplit=-1)¶
使用 sep 作为分隔符字符串,将二进制序列拆分为相同类型的子序列。如果给出了 maxsplit 且为非负数,则最多执行 maxsplit 次拆分(因此,列表最多包含
maxsplit+1
个元素)。如果未指定 maxsplit 或为-1
,则拆分次数没有限制(进行所有可能的拆分)。如果给出了 sep,则连续的分隔符不会合并,并被视为分隔空子序列(例如,
b'1,,2'.split(b',')
返回[b'1', b'', b'2']
)。sep 参数可以包含多字节序列作为单个分隔符。拆分空序列并指定分隔符会返回[b'']
或[bytearray(b'')]
,具体取决于要拆分的对象的类型。sep 参数可以是任何 类字节对象。例如:
>>> b'1,2,3'.split(b',') [b'1', b'2', b'3'] >>> b'1,2,3'.split(b',', maxsplit=1) [b'1', b'2,3'] >>> b'1,2,,3,'.split(b',') [b'1', b'2', b'', b'3', b''] >>> b'1<>2<>3<4'.split(b'<>') [b'1', b'2', b'3<4']
如果未指定 sep 或为
None
,则应用不同的拆分算法:连续的 ASCII 空白字符被视为单个分隔符,并且结果不包含开头或结尾的空字符串(如果序列有前导或尾随空白)。因此,在未指定分隔符的情况下拆分空序列或仅由 ASCII 空白字符组成的序列会返回[]
。例如:
>>> b'1 2 3'.split() [b'1', b'2', b'3'] >>> b'1 2 3'.split(maxsplit=1) [b'1', b'2 3'] >>> b' 1 2 3 '.split() [b'1', b'2', b'3']
- bytes.strip(bytes=None, /)¶
- bytearray.strip(bytes=None, /)¶
返回一个副本,其中删除了指定的开头和结尾字节。bytes 参数是一个二进制序列,指定要删除的字节值集合。如果省略或为
None
,则 bytes 参数默认为删除 ASCII 空白字符。bytes 参数不是前缀或后缀;而是,其所有值的组合都会被删除。>>> b' spacious '.strip() b'spacious' >>> b'www.example.com'.strip(b'cmowz.') b'example'
要删除的字节值的二进制序列可以是任何 类字节对象。
备注
此方法的 bytearray 版本不会就地操作 - 它始终生成新对象,即使未进行任何更改。
bytes 和 bytearray 对象上的以下方法假定使用 ASCII 兼容的二进制格式,不应用于处理任意二进制数据。请注意,此部分中的所有 bytearray 方法不会就地操作,而是生成新对象。
- bytes.capitalize()¶
- bytearray.capitalize()¶
返回序列的副本,其中每个字节都被解释为 ASCII 字符,第一个字节大写,其余字节小写。非 ASCII 字节值将保持不变。
备注
此方法的 bytearray 版本不会就地操作 - 它始终生成新对象,即使未进行任何更改。
- bytes.expandtabs(tabsize=8)¶
- bytearray.expandtabs(tabsize=8)¶
返回序列的副本,其中所有 ASCII 制表符都替换为一个或多个 ASCII 空格,具体取决于当前列和给定的制表符大小。制表符位置每 tabsize 字节出现一次(默认值为 8,制表符位置在列 0、8、16 等处)。要展开序列,当前列设置为零,然后逐字节检查序列。如果该字节是 ASCII 制表符(
b'\t'
),则在结果中插入一个或多个空格字符,直到当前列等于下一个制表符位置。(制表符本身不被复制)。如果当前字节是 ASCII 换行符(b'\n'
)或回车符(b'\r'
),则将其复制,并将当前列重置为零。任何其他字节值都将保持不变,并且当前列会增加一个,无论该字节值在打印时如何表示。>>> b'01\t012\t0123\t01234'.expandtabs() b'01 012 0123 01234' >>> b'01\t012\t0123\t01234'.expandtabs(4) b'01 012 0123 01234'
备注
此方法的 bytearray 版本不会就地操作 - 它始终生成新对象,即使未进行任何更改。
- bytes.isalnum()¶
- bytearray.isalnum()¶
如果序列中的所有字节都是字母 ASCII 字符或 ASCII 十进制数字,并且序列非空,则返回
True
,否则返回False
。字母 ASCII 字符是b'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
序列中的字节值。ASCII 十进制数字是b'0123456789'
序列中的字节值。例如:
>>> b'ABCabc1'.isalnum() True >>> b'ABC abc1'.isalnum() False
- bytes.isalpha()¶
- bytearray.isalpha()¶
如果序列中的所有字节都是字母 ASCII 字符,并且序列非空,则返回
True
,否则返回False
。字母 ASCII 字符是b'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
序列中的字节值。例如:
>>> b'ABCabc'.isalpha() True >>> b'ABCabc1'.isalpha() False
- bytes.isascii()¶
- bytearray.isascii()¶
如果序列为空或序列中的所有字节都是 ASCII,则返回
True
,否则返回False
。ASCII 字节的范围是 0-0x7F。在 3.7 版本加入。
- bytes.isdigit()¶
- bytearray.isdigit()¶
如果序列中的所有字节都是 ASCII 十进制数字,并且序列非空,则返回
True
,否则返回False
。ASCII 十进制数字是b'0123456789'
序列中的字节值。例如:
>>> b'1234'.isdigit() True >>> b'1.23'.isdigit() False
- bytes.islower()¶
- bytearray.islower()¶
如果序列中至少有一个小写 ASCII 字符且没有大写 ASCII 字符,则返回
True
,否则返回False
。例如:
>>> b'hello world'.islower() True >>> b'Hello world'.islower() False
小写 ASCII 字符是
b'abcdefghijklmnopqrstuvwxyz'
序列中的字节值。大写 ASCII 字符是b'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
序列中的字节值。
- bytes.isspace()¶
- bytearray.isspace()¶
如果序列中的所有字节都是 ASCII 空白字符,并且序列非空,则返回
True
,否则返回False
。ASCII 空白字符是b' \t\n\r\x0b\f'
(空格、制表符、换行符、回车符、垂直制表符、换页符)序列中的字节值。
- bytes.istitle()¶
- bytearray.istitle()¶
如果序列是 ASCII 标题化且序列非空,则返回
True
,否则返回False
。有关“标题化”的定义,请参阅bytes.title()
。例如:
>>> b'Hello World'.istitle() True >>> b'Hello world'.istitle() False
- bytes.isupper()¶
- bytearray.isupper()¶
如果序列中至少有一个大写 ASCII 字母字符且没有小写 ASCII 字符,则返回
True
,否则返回False
。例如:
>>> b'HELLO WORLD'.isupper() True >>> b'Hello world'.isupper() False
小写 ASCII 字符是
b'abcdefghijklmnopqrstuvwxyz'
序列中的字节值。大写 ASCII 字符是b'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
序列中的字节值。
- bytes.lower()¶
- bytearray.lower()¶
返回序列的副本,其中所有大写 ASCII 字符都转换为相应的小写字符。
例如:
>>> b'Hello World'.lower() b'hello world'
小写 ASCII 字符是
b'abcdefghijklmnopqrstuvwxyz'
序列中的字节值。大写 ASCII 字符是b'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
序列中的字节值。备注
此方法的 bytearray 版本不会就地操作 - 它始终生成新对象,即使未进行任何更改。
- bytes.splitlines(keepends=False)¶
- bytearray.splitlines(keepends=False)¶
返回二进制序列中的行的列表,在 ASCII 行边界处断开。此方法使用 通用换行符 方法拆分行。除非给定了 keepends 且为 true,否则行结尾符不包含在结果列表中。
例如:
>>> b'ab c\n\nde fg\rkl\r\n'.splitlines() [b'ab c', b'', b'de fg', b'kl'] >>> b'ab c\n\nde fg\rkl\r\n'.splitlines(keepends=True) [b'ab c\n', b'\n', b'de fg\r', b'kl\r\n']
与给出分隔符字符串 sep 时的
split()
不同,此方法对于空字符串返回空列表,并且尾部换行符不会导致产生额外的行。>>> b"".split(b'\n'), b"Two lines\n".split(b'\n') ([b''], [b'Two lines', b'']) >>> b"".splitlines(), b"One line\n".splitlines() ([], [b'One line'])
- bytes.swapcase()¶
- bytearray.swapcase()¶
返回序列的副本,其中所有小写 ASCII 字符都转换为相应的大写字符,反之亦然。
例如:
>>> b'Hello World'.swapcase() b'hELLO wORLD'
小写 ASCII 字符是
b'abcdefghijklmnopqrstuvwxyz'
序列中的字节值。大写 ASCII 字符是b'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
序列中的字节值。与
str.swapcase()
不同,对于二进制版本,始终有bin.swapcase().swapcase() == bin
。ASCII 中的大小写转换是双向的,即使这对于任意 Unicode 代码点通常不成立。备注
此方法的 bytearray 版本不会就地操作 - 它始终生成新对象,即使未进行任何更改。
- bytes.title()¶
- bytearray.title()¶
返回二进制序列的标题化版本,其中单词以大写 ASCII 字符开头,其余字符为小写。未区分大小写的字节值保持不变。
例如:
>>> b'Hello world'.title() b'Hello World'
小写 ASCII 字符是
b'abcdefghijklmnopqrstuvwxyz'
序列中的字节值。大写 ASCII 字符是b'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
序列中的字节值。所有其他字节值均未区分大小写。该算法使用一种简单的、与语言无关的单词定义,即将单词定义为连续字母的组。该定义在许多情况下都有效,但这意味着缩写和所有格中的撇号会形成单词边界,这可能不是期望的结果。
>>> b"they're bill's friends from the UK".title() b"They'Re Bill'S Friends From The Uk"
可以使用正则表达式构造一个解决撇号问题的变通方法。
>>> import re >>> def titlecase(s): ... return re.sub(rb"[A-Za-z]+('[A-Za-z]+)?", ... lambda mo: mo.group(0)[0:1].upper() + ... mo.group(0)[1:].lower(), ... s) ... >>> titlecase(b"they're bill's friends.") b"They're Bill's Friends."
备注
此方法的 bytearray 版本不会就地操作 - 它始终生成新对象,即使未进行任何更改。
printf
风格的字节格式化¶
备注
此处描述的格式化操作会显示各种怪癖,导致一些常见错误(例如,未能正确显示元组和字典)。如果打印的值可能是元组或字典,请将其包装在元组中。
Bytes 对象(bytes
/bytearray
)有一个独特的内置操作:%
运算符(模运算符)。这也被称为字节格式化或插值运算符。给定 format % values
(其中 format 是一个 bytes 对象),format 中的 % 转换说明符会被 values 的零个或多个元素替换。效果类似于 C 语言中的 sprintf()
。
如果 format 需要单个参数,values 可以是单个非元组对象。[5] 否则,values 必须是一个元组,其元素数量与格式 bytes 对象指定的数量完全一致,或者是一个单独的映射对象(例如,字典)。
转换规范包含两个或更多个字符,并具有以下组成部分,它们必须按此顺序出现:
标记规范开头的
'%'
字符。映射键(可选),由一系列括号括起来的字符组成(例如,
(somename)
)。转换标志(可选),它们会影响某些转换类型的結果。
最小字段宽度(可选)。如果指定为
'*'
(星号),则实际宽度将从values中的下一个元素读取,要转换的对象将出现在最小字段宽度和可选精度之后。精度(可选),给出为
'.'
(点)后跟精度。如果指定为'*'
(星号),则实际精度将从values中的下一个元素读取,要转换的值将出现在精度之后。长度修改符(可选)。
转换类型。
当右侧参数是字典(或其他映射类型)时,bytes 对象中的格式必须包含一个括号括起来的字典键,紧跟在 '%'
字符之后。映射键从映射中选择要格式化的值。例如:
>>> print(b'%(language)s has %(number)03d quote types.' %
... {b'language': b"Python", b"number": 2})
b'Python has 002 quote types.'
在这种情况下,格式中可能不会出现*
规范(因为它们需要顺序参数列表)。
转换标志字符是:
Flag |
含义 |
---|---|
|
转换将使用“备用形式”(如下定义)。 |
|
对于数字值,转换将使用零填充。 |
|
转换将左对齐(如果两者都给出,则覆盖 |
|
(空格)在有符号转换产生的正数(或空字符串)之前应留有一个空格。 |
|
符号字符( |
长度修改符(h
, l
, 或 L
)可能存在,但在 Python 中被忽略,因为它们不是必需的——所以例如%ld
与%d
相同。
转换类型是:
转换 |
含义 |
备注 |
---|---|---|
|
带符号整数十进制。 |
|
|
带符号整数十进制。 |
|
|
带符号八进制值。 |
(1) |
|
已弃用的类型——它与 |
(8) |
|
带符号十六进制(小写)。 |
(2) |
|
带符号十六进制(大写)。 |
(2) |
|
浮点指数格式(小写)。 |
(3) |
|
浮点指数格式(大写)。 |
(3) |
|
浮点十进制格式。 |
(3) |
|
浮点十进制格式。 |
(3) |
|
浮点格式。当指数小于 -4 或不小于精度时,使用小写指数格式,否则使用十进制格式。 |
(4) |
|
浮点格式。当指数小于 -4 或不小于精度时,使用大写指数格式,否则使用十进制格式。 |
(4) |
|
单个字节(接受整数或单个字节对象)。 |
|
|
字节(任何遵循 缓冲区协议 或具有 |
(5) |
|
|
(6) |
|
字节(使用 |
(5) |
|
|
(7) |
|
不转换参数,结果中产生一个 |
备注
备用形式会在第一个数字之前插入一个前导八进制说明符(
'0o'
)。备用形式会在第一个数字之前插入一个前导
'0x'
或'0X'
(取决于使用的是'x'
还是'X'
格式)。备用形式会导致结果始终包含小数点,即使小数点后面没有数字。
精度决定小数点后的位数,默认为 6。
备用形式会导致结果始终包含小数点,并且尾随零不会像通常那样被删除。
精度决定小数点前后有效数字的位数,默认为 6。
如果精度为
N
,则输出将截断为N
个字符。b'%s'
已弃用,但在 3.x 系列中不会被移除。b'%r'
已弃用,但在 3.x 系列中不会被移除。请参阅 PEP 237。
备注
此方法的 bytearray 版本不会就地操作 - 它始终生成新对象,即使未进行任何更改。
参见
PEP 461 - 为 bytes 和 bytearray 添加 % 格式化。
在 3.5 版本加入。
内存视图¶
memoryview
对象允许 Python 代码在不复制的情况下访问支持 缓冲区协议 的对象的内部数据。
- class memoryview(object)¶
创建引用 object 的
memoryview
。object 必须支持缓冲区协议。内置对象,如bytes
和bytearray
,都支持缓冲区协议。memoryview
具有元素的概念,它是起源对象处理的原子内存单元。对于像bytes
和bytearray
这样的许多简单类型,一个元素是单个字节,但像array.array
这样的其他类型可能具有更大的元素。len(view)
等于tolist
的长度,这是视图的嵌套列表表示。如果view.ndim = 1
,则它等于视图中的元素数。版本 3.12 中已更改: 如果
view.ndim == 0
,len(view)
现在会引发TypeError
而不是返回 1。itemsize
属性将为您提供单个元素的字节数。memoryview
支持切片和索引来暴露其数据。一维切片将生成子视图。>>> v = memoryview(b'abcefg') >>> v[1] 98 >>> v[-1] 103 >>> v[1:4] <memory at 0x7f3ddc9f4350> >>> bytes(v[1:4]) b'bce'
如果
format
是struct
模块中的原生格式说明符之一,则使用整数或整数元组进行索引也受支持,并返回具有正确类型的单个元素。一维 memoryview 可以用整数或单整数元组索引。多维 memoryview 可以用恰好包含 ndim 个整数的元组索引,其中 ndim 是维度的数量。零维 memoryview 可以用空元组索引。这是一个具有非字节格式的示例:
>>> import array >>> a = array.array('l', [-11111111, 22222222, -33333333, 44444444]) >>> m = memoryview(a) >>> m[0] -11111111 >>> m[-1] 44444444 >>> m[::2].tolist() [-11111111, -33333333]
如果底层对象是可写的,则 memoryview 支持一维切片赋值。不允许调整大小。
>>> data = bytearray(b'abcefg') >>> v = memoryview(data) >>> v.readonly False >>> v[0] = ord(b'z') >>> data bytearray(b'zbcefg') >>> v[1:4] = b'123' >>> data bytearray(b'z123fg') >>> v[2:3] = b'spam' Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: memoryview assignment: lvalue and rvalue have different structures >>> v[2:6] = b'spam' >>> data bytearray(b'z1spam')
格式为“B”、“b”或“c”的可哈希(只读)类型的单字节 memoryview 也可哈希。哈希定义为
hash(m) == hash(m.tobytes())
。>>> v = memoryview(b'abcefg') >>> hash(v) == hash(b'abcefg') True >>> hash(v[2:4]) == hash(b'ce') True >>> hash(v[::-2]) == hash(b'abcefg'[::-2]) True
版本 3.3 中已更改: 现在可以对一维 memoryview 进行切片。格式为“B”、“b”或“c”的一维 memoryview 现在是可哈希的。
版本 3.4 中已更改: memoryview 现在已自动注册到
collections.abc.Sequence
。版本 3.5 中已更改: memoryview 现在可以用整数元组进行索引。
版本 3.14 中已更改: memoryview 现在是泛型类型。
memoryview
有几个方法:- __eq__(exporter)¶
当使用
struct
语法解释各自的格式代码时,如果 memoryview 和 PEP 3118 导出器具有等效的形状且所有对应值相等,则它们相等。对于目前
tolist()
支持的struct
格式字符串的子集,v
和w
相等,当且仅当v.tolist() == w.tolist()
。>>> import array >>> a = array.array('I', [1, 2, 3, 4, 5]) >>> b = array.array('d', [1.0, 2.0, 3.0, 4.0, 5.0]) >>> c = array.array('b', [5, 3, 1]) >>> x = memoryview(a) >>> y = memoryview(b) >>> x == a == y == b True >>> x.tolist() == a.tolist() == y.tolist() == b.tolist() True >>> z = y[::-2] >>> z == c True >>> z.tolist() == c.tolist() True
如果任一格式字符串不受
struct
模块支持,则对象将始终比较为不相等(即使格式字符串和缓冲区内容相同)。>>> from ctypes import BigEndianStructure, c_long >>> class BEPoint(BigEndianStructure): ... _fields_ = [("x", c_long), ("y", c_long)] ... >>> point = BEPoint(100, 200) >>> a = memoryview(point) >>> b = memoryview(point) >>> a == point False >>> a == b False
请注意,与浮点数一样,
v is w
对于 memoryview 对象不意味着v == w
。版本 3.3 中已更改: 以前的版本会忽略项目格式和逻辑数组结构,直接比较原始内存。
- tobytes(order='C')¶
返回缓冲区中的数据作为字节字符串。这相当于在 memoryview 上调用
bytes
构造函数。>>> m = memoryview(b"abc") >>> m.tobytes() b'abc' >>> bytes(m) b'abc'
对于非连续数组,结果等于所有元素转换为字节的展平列表表示。
tobytes()
支持所有格式字符串,包括struct
模块语法中不包含的格式字符串。版本 3.8 中已添加: order 可以是 {‘C’, ‘F’, ‘A’}。当 order 为 ‘C’ 或 ‘F’ 时,原始数组的数据被转换为 C 或 Fortran 顺序。对于连续视图,‘A’ 返回物理内存的精确副本。特别地,内存中的 Fortran 顺序被保留。对于非连续视图,数据首先被转换为 C。order=None 与 order=’C’ 相同。
- hex(*, bytes_per_sep=1)¶
- hex(sep, bytes_per_sep=1)
返回一个字符串对象,其中缓冲区中的每个字节都用两个十六进制数字表示。
>>> m = memoryview(b"abc") >>> m.hex() '616263'
在 3.5 版本加入。
版本 3.8 中已更改: 类似于
bytes.hex()
,memoryview.hex()
现在支持可选的 sep 和 bytes_per_sep 参数,用于在十六进制输出的字节之间插入分隔符。
- tolist()¶
返回缓冲区中的数据作为元素列表。
>>> memoryview(b'abc').tolist() [97, 98, 99] >>> import array >>> a = array.array('d', [1.1, 2.2, 3.3]) >>> m = memoryview(a) >>> m.tolist() [1.1, 2.2, 3.3]
- toreadonly()¶
返回 memoryview 对象的只读版本。原始 memoryview 对象保持不变。
>>> m = memoryview(bytearray(b'abc')) >>> mm = m.toreadonly() >>> mm.tolist() [97, 98, 99] >>> mm[0] = 42 Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: cannot modify read-only memory >>> m[0] = 43 >>> mm.tolist() [43, 98, 99]
在 3.8 版本加入。
- release()¶
释放 memoryview 对象公开的底层缓冲区。许多对象在对其持有视图时会采取特殊操作(例如,
bytearray
会暂时禁止调整大小);因此,调用 release() 方法有助于尽快删除这些限制(并释放任何悬空资源)。调用此方法后,对视图的任何后续操作都会引发
ValueError
(除了release()
本身,它可以被多次调用)。>>> m = memoryview(b'abc') >>> m.release() >>> m[0] Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: operation forbidden on released memoryview object
上下文管理协议可以使用
with
语句实现类似的效果。>>> with memoryview(b'abc') as m: ... m[0] ... 97 >>> m[0] Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: operation forbidden on released memoryview object
在 3.2 版本加入。
- cast(format, /)¶
- cast(format, shape, /)
将 memoryview 转换为新的格式或形状。shape 的默认值是
[byte_length//new_itemsize]
,这意味着结果视图将是一维的。返回值是一个新的 memoryview,但缓冲区本身不会被复制。支持的转换包括 1D -> C-contiguous 和 C-contiguous -> 1D。目标格式仅限于
struct
语法中的单个元素本机格式。其中一种格式必须是字节格式(“B”、“b”或“c”)。结果的字节长度必须与原始长度相同。请注意,所有字节长度可能取决于操作系统。将 1D/long 转换为 1D/unsigned bytes
>>> import array >>> a = array.array('l', [1,2,3]) >>> x = memoryview(a) >>> x.format 'l' >>> x.itemsize 8 >>> len(x) 3 >>> x.nbytes 24 >>> y = x.cast('B') >>> y.format 'B' >>> y.itemsize 1 >>> len(y) 24 >>> y.nbytes 24
将 1D/unsigned bytes 转换为 1D/char
>>> b = bytearray(b'zyz') >>> x = memoryview(b) >>> x[0] = b'a' Traceback (most recent call last): ... TypeError: memoryview: invalid type for format 'B' >>> y = x.cast('c') >>> y[0] = b'a' >>> b bytearray(b'ayz')
将 1D/bytes 转换为 3D/ints,再转换为 1D/signed char
>>> import struct >>> buf = struct.pack("i"*12, *list(range(12))) >>> x = memoryview(buf) >>> y = x.cast('i', shape=[2,2,3]) >>> y.tolist() [[[0, 1, 2], [3, 4, 5]], [[6, 7, 8], [9, 10, 11]]] >>> y.format 'i' >>> y.itemsize 4 >>> len(y) 2 >>> y.nbytes 48 >>> z = y.cast('b') >>> z.format 'b' >>> z.itemsize 1 >>> len(z) 48 >>> z.nbytes 48
将 1D/unsigned long 转换为 2D/unsigned long
>>> buf = struct.pack("L"*6, *list(range(6))) >>> x = memoryview(buf) >>> y = x.cast('L', shape=[2,3]) >>> len(y) 2 >>> y.nbytes 48 >>> y.tolist() [[0, 1, 2], [3, 4, 5]]
在 3.3 版本加入。
版本 3.5 中已更改: 在转换为字节视图时,源格式不再受限制。
- count(value, /)¶
计算 value 出现的次数。
在 3.14 版本加入。
- index(value, start=0, stop=sys.maxsize, /)¶
还有一些只读属性可用
- obj¶
memoryview 的底层对象
>>> b = bytearray(b'xyz') >>> m = memoryview(b) >>> m.obj is b True
在 3.3 版本加入。
- nbytes¶
nbytes == product(shape) * itemsize == len(m.tobytes())
。这是数组在连续表示中使用的大小(以字节为单位)。它不一定等于len(m)
。>>> import array >>> a = array.array('i', [1,2,3,4,5]) >>> m = memoryview(a) >>> len(m) 5 >>> m.nbytes 20 >>> y = m[::2] >>> len(y) 3 >>> y.nbytes 12 >>> len(y.tobytes()) 12
多维数组
>>> import struct >>> buf = struct.pack("d"*12, *[1.5*x for x in range(12)]) >>> x = memoryview(buf) >>> y = x.cast('d', shape=[3,4]) >>> y.tolist() [[0.0, 1.5, 3.0, 4.5], [6.0, 7.5, 9.0, 10.5], [12.0, 13.5, 15.0, 16.5]] >>> len(y) 3 >>> y.nbytes 96
在 3.3 版本加入。
- readonly¶
一个布尔值,指示内存是否只读。
- format¶
一个字符串,包含视图中每个元素的格式(采用
struct
模块风格)。Memoryview 可以从具有任意格式字符串的导出器创建,但某些方法(例如tolist()
)仅限于本机单个元素格式。版本 3.3 中已更改: 格式
'B'
现在根据 struct 模块语法进行处理。这意味着memoryview(b'abc')[0] == b'abc'[0] == 97
。
- itemsize¶
memoryview 中每个元素的大小(以字节为单位)
>>> import array, struct >>> m = memoryview(array.array('H', [32000, 32001, 32002])) >>> m.itemsize 2 >>> m[0] 32000 >>> struct.calcsize('H') == m.itemsize True
- ndim¶
一个整数,指示内存表示的多维数组的维数。
- suboffsets¶
内部用于 PIL 风格的数组。此值仅供参考。
- c_contiguous¶
一个布尔值,指示内存是否为 C-contiguous。
在 3.3 版本加入。
- f_contiguous¶
一个布尔值,指示内存是否为 Fortran contiguous。
在 3.3 版本加入。
- contiguous¶
一个布尔值,指示内存是否为contiguous。
在 3.3 版本加入。
Set 类型 — set
, frozenset
¶
Set 对象是无序的、不重复的、可哈希对象的集合。常见用途包括成员资格测试、从序列中删除重复项以及计算交集、并集、差集和对称差集等数学运算。(有关其他容器,请参阅内置的 dict
、list
和 tuple
类,以及 collections
模块。)
与所有集合一样,集合支持 x in set
、len(set)
和 for x in set
。由于是无序集合,集合不记录元素位置或插入顺序。因此,集合不支持索引、切片或其他类序列行为。
目前有两种内置的集合类型:set
和 frozenset
。set
类型是可变的——内容可以通过 add()
和 remove()
等方法进行更改。由于它是可变的,因此没有哈希值,不能用作字典键或另一个集合的元素。frozenset
类型是不可变的且可哈希——创建后其内容无法更改;因此,它可以作为字典键或另一个集合的元素。
非空集合(非 frozensets)可以通过将逗号分隔的元素列表放在大括号内创建,例如:{'jack', 'sjoerd'}
,这是一种除了 set
构造函数之外的创建方式。
两个类的构造函数工作方式相同
- class set(iterable=(), /)¶
- class frozenset(iterable=(), /)¶
返回一个新的 set 或 frozenset 对象,其元素来自 iterable。set 的元素必须是可哈希的。要表示集合的集合,内部集合必须是
frozenset
对象。如果未指定 iterable,则返回一个空 set。Set 可通过多种方式创建
使用大括号内的逗号分隔的元素列表:
{'jack', 'sjoerd'}
使用 set 推导式:
{c for c in 'abracadabra' if c not in 'abc'}
使用类型构造函数:
set()
,set('foobar')
,set(['a', 'b', 'foo'])
- len(s)
返回集合 s 中的元素数量(s 的基数)。
- x in s
测试 x 是否为 s 的成员。
- x not in s
测试 x 是否不是 s 的成员。
- isdisjoint(other, /)¶
如果集合与 other 没有共同的元素,则返回
True
。当且仅当它们的交集为空集时,集合才是不相交的。
- issubset(other, /)¶
- set <= other
测试集合中的每个元素是否都在 other 中。
- set < other
测试集合是否是 other 的真子集,即
set <= other and set != other
。
- issuperset(other, /)¶
- set >= other
测试 other 中的每个元素是否都在集合中。
- set > other
测试集合是否是 other 的真超集,即
set >= other and set != other
。
- union(*others)¶
- set | other | ...
返回一个包含来自集合和所有其他集合的元素的新集合。
- intersection(*others)¶
- set & other & ...
返回一个包含来自集合和所有其他集合的共有元素的的新集合。
- difference(*others)¶
- set - other - ...
返回一个包含来自集合但不在其他集合中的元素的新集合。
- symmetric_difference(other, /)¶
- set ^ other
返回一个包含仅存在于集合或 other 中但不同时存在于两者的元素的新集合。
- copy()¶
返回集合的浅拷贝。
注意,非运算符版本的
union()
、intersection()
、difference()
、symmetric_difference()
、issubset()
和issuperset()
方法将接受任何可迭代对象作为参数。相比之下,它们的基于运算符的对应项要求其参数为集合。这避免了容易出错的构造,如set('abc') & 'cbs'
,而是使用更具可读性的set('abc').intersection('cbs')
。set
和frozenset
都支持集合到集合的比较。两个集合相等当且仅当每个集合的元素都包含在另一个集合中(每个集合是另一个集合的子集)。一个集合小于另一个集合当且仅当第一个集合是第二个集合的真子集(是子集,但不是相等)。一个集合大于另一个集合当且仅当第一个集合是第二个集合的真超集(是超集,但不是相等)。set
的实例与frozenset
的实例基于它们的成员进行比较。例如,set('abc') == frozenset('abc')
返回True
,set('abc') in set([frozenset('abc')])
也返回True
。子集和相等比较不适用于总序函数。例如,任何两个非空不相交的集合都不相等,并且互不为子集,因此所有以下项都返回
False
:a<b
、a==b
或a>b
。由于集合只定义了偏序(子集关系),因此
list.sort()
方法对集合列表的输出是未定义的。集合元素,如同字典键一样,必须是可哈希的。
混合
set
实例和frozenset
的二进制操作返回第一个操作数的类型。例如:frozenset('ab') | set('bc')
返回frozenset
的实例。下表列出了
set
支持的、但不可用于frozenset
不可变实例的操作- update(*others)¶
- set |= other | ...
更新集合,添加来自所有其他集合的元素。
- intersection_update(*others)¶
- set &= other & ...
更新集合,仅保留在集合本身和所有其他集合中找到的元素。
- difference_update(*others)¶
- set -= other | ...
更新集合,删除在其他集合中找到的元素。
- symmetric_difference_update(other, /)¶
- set ^= other
更新集合,仅保留存在于任一集合中但不同时存在于两者的元素。
- add(elem, /)¶
将元素 elem 添加到集合中。
- discard(elem, /)¶
如果元素 elem 存在,则从集合中删除它。
- clear()¶
从集合中删除所有元素。
注意,非运算符版本的
update()
、intersection_update()
、difference_update()
和symmetric_difference_update()
方法将接受任何可迭代对象作为参数。注意,
__contains__()
、remove()
和discard()
方法的 elem 参数可以是集合。为了支持搜索等效的 frozenset,会从 elem 创建一个临时的 frozenset。
Mapping 类型 — dict
¶
Mapping 对象将可哈希值映射到任意对象。Mappings 是可变对象。目前只有一个标准的 mapping 类型,即字典。(有关其他容器,请参阅内置的 list
、set
和 tuple
类,以及 collections
模块。)
字典的键是*几乎*任意值。不可哈希的值,即包含列表、字典或其他可变类型(按值而不是按对象身份比较)的值,不能用作键。值相等(例如 1
、1.0
和 True
)可以互换使用来索引同一个字典条目。
- class dict(**kwargs)¶
- class dict(mapping, /, **kwargs)
- class dict(iterable, /, **kwargs)
返回一个由可选位置参数和可能为空的关键字参数集初始化的新字典。
字典可通过多种方式创建
使用大括号内的逗号分隔的
key: value
对列表:{'jack': 4098, 'sjoerd': 4127}
或{4098: 'jack', 4127: 'sjoerd'}
使用 dict 推导式:
{}
,{x: x ** 2 for x in range(10)}
使用类型构造函数:
dict()
,dict([('foo', 100), ('bar', 200)])
,dict(foo=100, bar=200)
如果未提供位置参数,则创建一个空字典。如果提供了位置参数并且它定义了
keys()
方法,则通过使用该方法返回的每个键调用参数的__getitem__()
来创建字典。否则,位置参数必须是一个可迭代对象。可迭代对象的每个项本身必须是一个只包含两个元素的 iterable。每个项的第一个元素成为新字典中的键,第二个元素成为相应的值。如果一个键出现多次,该键的最后一个值将成为新字典中的相应值。如果提供了关键字参数,则将关键字参数及其值添加到由位置参数创建的字典中。如果要添加的键已存在,则关键字参数的值将替换来自位置参数的值。
提供关键字参数(如第一个示例所示)仅适用于有效的 Python 标识符作为键的情况。否则,可以使用任何有效的键。
字典当且仅当它们具有相同的
(key, value)
对时才相等(忽略顺序)。顺序比较(‘<’, ‘<=’, ‘>=’, ‘>’)会引发TypeError
。为了说明字典创建和相等性,以下所有示例都返回一个与{"one": 1, "two": 2, "three": 3}
相等的字典>>> a = dict(one=1, two=2, three=3) >>> b = {'one': 1, 'two': 2, 'three': 3} >>> c = dict(zip(['one', 'two', 'three'], [1, 2, 3])) >>> d = dict([('two', 2), ('one', 1), ('three', 3)]) >>> e = dict({'three': 3, 'one': 1, 'two': 2}) >>> f = dict({'one': 1, 'three': 3}, two=2) >>> a == b == c == d == e == f True
提供关键字参数(如第一个示例所示)仅适用于有效的 Python 标识符作为键的情况。否则,可以使用任何有效的键。
字典保留插入顺序。请注意,更新键不会影响顺序。删除后添加的键会插入到末尾。
>>> d = {"one": 1, "two": 2, "three": 3, "four": 4} >>> d {'one': 1, 'two': 2, 'three': 3, 'four': 4} >>> list(d) ['one', 'two', 'three', 'four'] >>> list(d.values()) [1, 2, 3, 4] >>> d["one"] = 42 >>> d {'one': 42, 'two': 2, 'three': 3, 'four': 4} >>> del d["two"] >>> d["two"] = None >>> d {'one': 42, 'three': 3, 'four': 4, 'two': None}
版本 3.7 中已更改: 字典顺序保证为插入顺序。此行为是 CPython 从 3.6 开始的实现细节。
以下是字典支持的操作(因此,自定义映射类型也应支持这些操作)
- list(d)
返回字典 d 中所有键的列表。
- len(d)
返回字典 d 中的项数。
- d[key]
返回 d 中键为 key 的项。如果 key 不在映射中,则引发
KeyError
。如果 dict 的子类定义了
__missing__()
方法且 key 不存在,则d[key]
操作将使用键 key 作为参数调用该方法。然后d[key]
操作返回或引发__missing__(key)
调用所返回或引发的任何内容。没有其他操作或方法会调用__missing__()
。如果未定义__missing__()
,则引发KeyError
。__missing__()
必须是一个方法;它不能是实例变量。>>> class Counter(dict): ... def __missing__(self, key): ... return 0 ... >>> c = Counter() >>> c['red'] 0 >>> c['red'] += 1 >>> c['red'] 1
上面的示例显示了
collections.Counter
实现的一部分。另一个__missing__()
方法由collections.defaultdict
使用。
- d[key] = value
将 d[key] 设置为 value。
- del d[key]
从 d 中删除
d[key]
。如果 key 不在映射中,则引发KeyError
。
- key in d
如果 d 有键 key,则返回
True
,否则返回False
。
- key not in d
等同于
not key in d
。
- iter(d)
返回字典键的迭代器。这是
iter(d.keys())
的快捷方式。
- clear()¶
从字典中删除所有项。
- copy()¶
返回字典的浅拷贝。
- classmethod fromkeys(iterable, value=None, /)¶
创建一个新的字典,其键来自 iterable,值设置为 value。
fromkeys()
是一个类方法,它返回一个新字典。value 的默认值为None
。所有值都指向单个实例,因此 value 是可变对象(如空列表)通常没有意义。要获得不同的值,请改用 dict 推导式。
- get(key, default=None, /)¶
如果 key 在字典中,则返回其值;否则返回 default。如果未提供 default,则默认值为
None
,因此此方法永远不会引发KeyError
。
- pop(key, /)¶
- pop(key, default, /)
如果 key 在字典中,则删除它并返回其值;否则返回 default。如果未提供 default 且 key 不在字典中,则引发
KeyError
。
- popitem()¶
从字典中删除并返回一个
(key, value)
对。对按 LIFO 顺序返回。popitem()
对于破坏性地迭代字典很有用,如集合算法中常用的那样。如果字典为空,调用popitem()
会引发KeyError
。版本 3.7 中已更改: LIFO 顺序现在已保证。在先前版本中,
popitem()
会返回一个任意的键/值对。
- reversed(d)
返回字典键的反向迭代器。这是
reversed(d.keys())
的快捷方式。在 3.8 版本加入。
- setdefault(key, default=None, /)¶
如果 key 在字典中,则返回其值。如果不在,则插入 key,值为 default,并返回 default。default 默认为
None
。
- update(**kwargs)¶
- update(mapping, /, **kwargs)
- update(iterable, /, **kwargs)
使用来自 mapping 或 iterable 和 kwargs 的键/值对更新字典,覆盖现有键。返回
None
。update()
接受带有keys()
方法的另一个对象(在这种情况下,将使用从方法返回的每个键调用__getitem__()
)或键/值对的可迭代对象(作为元组或其他长度为二的 iterable)。如果指定了关键字参数,则字典随后将使用这些键/值对进行更新:d.update(red=1, blue=2)
。
- values()¶
返回字典值的视图。请参阅视图对象文档。
一个
dict.values()
视图与另一个视图之间的相等性比较将始终返回False
。这也适用于将dict.values()
与自身进行比较的情况。>>> d = {'a': 1} >>> d.values() == d.values() False
- d | other
创建一个新字典,其中包含 d 和 other 的合并键值对,两者都必须是字典。当 d 和 other 共享键时,other 的值具有优先权。
在 3.9 版本中新增。
- d |= other
使用 other 的键和值更新字典 d,other 可以是 mapping 或键/值对的 iterable。当 d 和 other 共享键时,other 的值具有优先权。
在 3.9 版本中新增。
字典和字典视图是可逆的。
>>> d = {"one": 1, "two": 2, "three": 3, "four": 4} >>> d {'one': 1, 'two': 2, 'three': 3, 'four': 4} >>> list(reversed(d)) ['four', 'three', 'two', 'one'] >>> list(reversed(d.values())) [4, 3, 2, 1] >>> list(reversed(d.items())) [('four', 4), ('three', 3), ('two', 2), ('one', 1)]
版本 3.8 中已更改: 字典现在是可逆的。
参见
types.MappingProxyType
可用于创建 dict
的只读视图。
字典视图对象¶
由 dict.keys()
、dict.values()
和 dict.items()
返回的对象是*视图对象*。它们提供对字典条目的动态视图,这意味着当字典发生变化时,视图会反映这些变化。
字典视图可以迭代以产生各自的数据,并且支持成员资格测试
- len(dictview)
返回字典中的条目数。
- iter(dictview)
返回字典的键、值或项(表示为
(key, value)
元组)的迭代器。键和值按插入顺序迭代。这允许使用
zip()
创建(value, key)
对:pairs = zip(d.values(), d.keys())
。创建相同列表的另一种方法是pairs = [(v, k) for (k, v) in d.items()]
。在迭代视图时添加或删除字典中的条目可能会引发
RuntimeError
或未能迭代所有条目。版本 3.7 中已更改: 字典顺序保证为插入顺序。
- x in dictview
如果 x 存在于底层字典的键、值或项中(在后一种情况下,x 应为
(key, value)
元组),则返回True
。
- reversed(dictview)
返回字典的键、值或项的反向迭代器。视图将按插入顺序的反向迭代。
版本 3.8 中已更改: 字典视图现在是可逆的。
- dictview.mapping
返回一个
types.MappingProxyType
,它包装了视图引用的原始字典。在 3.10 版本加入。
键视图是类似集合的,因为它们的条目是唯一的且可哈希的。项视图也具有类似集合的操作,因为 (key, value) 对是唯一的且键是可哈希的。如果项视图中的所有值也都是可哈希的,那么项视图就可以与其他集合进行互操作。(值视图不被视为类似集合的,因为其中的条目通常不是唯一的。)对于类似集合的视图,抽象基类 collections.abc.Set
中定义的所有操作(例如,==
、<
或 ^
)都可用。(在使用集合运算符时,类似集合的视图接受任何可迭代对象作为另一个操作数,而集合只接受集合作为输入。)
字典视图使用的示例
>>> dishes = {'eggs': 2, 'sausage': 1, 'bacon': 1, 'spam': 500}
>>> keys = dishes.keys()
>>> values = dishes.values()
>>> # iteration
>>> n = 0
>>> for val in values:
... n += val
...
>>> print(n)
504
>>> # keys and values are iterated over in the same order (insertion order)
>>> list(keys)
['eggs', 'sausage', 'bacon', 'spam']
>>> list(values)
[2, 1, 1, 500]
>>> # view objects are dynamic and reflect dict changes
>>> del dishes['eggs']
>>> del dishes['sausage']
>>> list(keys)
['bacon', 'spam']
>>> # set operations
>>> keys & {'eggs', 'bacon', 'salad'}
{'bacon'}
>>> keys ^ {'sausage', 'juice'} == {'juice', 'sausage', 'bacon', 'spam'}
True
>>> keys | ['juice', 'juice', 'juice'] == {'bacon', 'spam', 'juice'}
True
>>> # get back a read-only proxy for the original dictionary
>>> values.mapping
mappingproxy({'bacon': 1, 'spam': 500})
>>> values.mapping['spam']
500
Context Manager 类型¶
Python 的 with
语句支持由 context manager 定义的运行时上下文的概念。这是通过一对方法实现的,这些方法允许用户定义的类定义一个在语句体执行之前进入、在语句结束时退出的运行时上下文
- contextmanager.__enter__()¶
进入运行时上下文,并返回该对象或与运行时上下文相关的另一个对象。此方法返回的值绑定到使用此 context manager 的
with
语句的as
子句中的标识符。返回自身的 context manager 的一个例子是文件对象。文件对象从 __enter__() 返回自身,以便
open()
可以在with
语句中使用作为上下文表达式。返回相关对象的 context manager 的一个例子是由
decimal.localcontext()
返回的。这些管理器将活动的 decimal 上下文设置为原始 decimal 上下文的副本,然后返回该副本。这允许在with
语句的正文中对当前 decimal 上下文进行更改,而不会影响with
语句外的代码。
- contextmanager.__exit__(exc_type, exc_val, exc_tb)¶
退出运行时上下文,并返回一个布尔标志,指示是否应抑制发生的任何异常。如果在执行
with
语句的主体时发生异常,则参数包含异常类型、值和回溯信息。否则,所有三个参数都为None
。从此方法返回真值将导致
with
语句抑制异常,并继续执行with
语句之后的下一条语句。否则,在方法完成执行后,异常将继续传播。在此方法执行期间发生的异常将替换在with
语句主体中发生的任何异常。引发的异常不应被显式重新引发——相反,该方法应返回一个假值,以指示该方法已成功完成并且不希望抑制已引发的异常。这允许上下文管理代码轻松检测
__exit__()
方法是否实际上失败。
Python 定义了几个 context manager 来支持轻松的线程同步、文件的及时关闭或其他对象,以及更简单的活动 decimal 算术上下文操作。具体类型除实现 context management protocol 外,不作特殊处理。有关一些示例,请参阅 contextlib
模块。
Python 的生成器和 contextlib.contextmanager
装饰器提供了一种方便的方式来实现这些协议。如果一个生成器函数被 contextlib.contextmanager
装饰器装饰,它将返回一个实现必要的 __enter__()
和 __exit__()
方法的 context manager,而不是未装饰的生成器函数产生的迭代器。
请注意,Python/C API 中的 Python 对象类型结构没有为这些方法设置特定的槽。希望定义这些方法的扩展类型必须将它们提供为普通的可 Python 访问方法。与设置运行时上下文的开销相比,查找单个类字典的开销可以忽略不计。
Type Annotation 类型 — Generic Alias, Union¶
类型注解的核心内置类型是 Generic Alias 和 Union。
Generic Alias 类型¶
GenericAlias
对象通常通过下标一个类来创建。它们最常用于容器类,如 list
或 dict
。例如,list[int]
是通过用参数 int
下标 list
类创建的 GenericAlias
对象。GenericAlias
对象主要用于类型注解。
备注
通常只能下标实现特殊方法 __class_getitem__()
的类。
GenericAlias
对象充当泛型类型的代理,实现*参数化泛型*。
对于容器类,提供给类下标的参数可以指示对象所包含元素的类型。例如,set[bytes]
可用于类型注解,以表示一个所有元素都为 bytes
类型的 set
。
对于定义了 __class_getitem__()
但不是容器的类,提供给类下标的参数通常会指示对象上定义的某个或多个方法的返回类型。例如,正则表达式
可用于 str
数据类型和 bytes
数据类型。
如果
x = re.search('foo', 'foo')
,则x
将是一个 re.Match 对象,其中x.group(0)
和x[0]
的返回值都将是str
类型。我们可以使用GenericAlias
re.Match[str]
在类型注解中表示这种类型的对象。如果
y = re.search(b'bar', b'bar')
(注意bytes
的b
),则y
也将是re.Match
的实例,但y.group(0)
和y[0]
的返回值都将是bytes
类型。在类型注解中,我们将用re.Match[bytes]
表示这种 re.Match 对象。
GenericAlias
对象是 types.GenericAlias
类的实例,它也可以用来直接创建 GenericAlias
对象。
- T[X, Y, ...]
创建一个
GenericAlias
,表示由类型 X、Y 等参数化的类型 T(具体取决于所使用的T
)。例如,一个期望包含float
元素的list
的函数def average(values: list[float]) -> float: return sum(values) / len(values)
另一个使用映射对象的示例,使用
dict
,它是一种通用类型,需要两个类型参数来表示键类型和值类型。在此示例中,该函数需要一个键类型为str
、值为int
的dict
。def send_post_request(url: str, body: dict[str, int]) -> None: ...
内置函数 isinstance()
和 issubclass()
不接受 GenericAlias
类型作为第二个参数。
>>> isinstance([1, 2], list[str])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: isinstance() argument 2 cannot be a parameterized generic
Python 运行时不会强制执行 类型注解。这同样适用于泛型类型及其类型参数。当从 GenericAlias
创建容器对象时,容器中的元素不会根据其类型进行检查。例如,以下代码不推荐使用,但可以运行而不会出错:
>>> t = list[str]
>>> t([1, 2, 3])
[1, 2, 3]
此外,参数化泛型在对象创建过程中会擦除类型参数。
>>> t = list[str]
>>> type(t)
<class 'types.GenericAlias'>
>>> l = t()
>>> type(l)
<class 'list'>
对泛型调用 repr()
或 str()
会显示参数化类型。
>>> repr(list[int])
'list[int]'
>>> str(list[int])
'list[int]'
泛型容器的 __getitem__()
方法会引发异常,以防止 dict[str][str]
等错误。
>>> dict[str][str]
Traceback (most recent call last):
...
TypeError: dict[str] is not a generic class
然而,当使用 类型变量 时,此类表达式是有效的。索引必须包含与 GenericAlias
对象 __args__
中的类型变量项一样多的元素。
>>> from typing import TypeVar
>>> Y = TypeVar('Y')
>>> dict[str, Y][int]
dict[str, int]
标准泛型类¶
以下标准库类支持参数化泛型。此列表不详尽。
GenericAlias 对象的特殊属性¶
所有参数化泛型都实现了特殊的只读属性。
- genericalias.__origin__¶
此属性指向非参数化的泛型类。
>>> list[int].__origin__ <class 'list'>
- genericalias.__args__¶
此属性是一个
tuple
(可能长度为 1),包含传递给泛型类的原始__class_getitem__()
的泛型类型。>>> dict[str, list[int]].__args__ (<class 'str'>, list[int])
- genericalias.__parameters__¶
此属性是一个惰性计算的元组(可能为空),包含在
__args__
中找到的唯一类型变量。>>> from typing import TypeVar >>> T = TypeVar('T') >>> list[T].__parameters__ (~T,)
备注
具有
typing.ParamSpec
参数的GenericAlias
对象可能没有正确的__parameters__
,因为typing.ParamSpec
主要用于静态类型检查。
- genericalias.__unpacked__¶
一个布尔值,如果别名已通过
*
运算符解包(参见TypeVarTuple
),则为 True。在 3.11 版本中新增。
参见
- PEP 484 - 类型提示
介绍 Python 的类型注解框架。
- PEP 585 - 标准集合中的类型提示泛型
介绍原生参数化标准库类(前提是它们实现了特殊的类方法
__class_getitem__()
)的能力。- 泛型、用户自定义泛型 和
typing.Generic
关于如何实现可在运行时参数化并被静态类型检查器理解的泛型类的文档。
在 3.9 版本中新增。
联合类型¶
联合对象保存了多个 类型对象 上 |
(按位或)运算的值。这些类型主要用于 类型注解。联合类型表达式比下标引用 typing.Union
提供了更简洁的类型提示语法。
- X | Y | ...
定义一个联合对象,它包含类型 X、Y 等。
X | Y
表示 X 或 Y。它等同于typing.Union[X, Y]
。例如,以下函数需要一个类型为int
或float
的参数。def square(number: int | float) -> int | float: return number ** 2
备注
运行时不能使用
|
运算符来定义一个或多个成员是前向引用的联合。例如,int | "Foo"
(其中"Foo"
是对尚未定义的类的引用)在运行时会失败。对于包含前向引用的联合,请将整个表达式作为字符串提供,例如"int | Foo"
。
- union_object == other
联合对象可以与其他联合对象进行相等性测试。详细信息
联合的联合会被展平。
(int | str) | float == int | str | float
冗余类型会被移除。
int | str | int == int | str
比较联合时,顺序会被忽略。
int | str == str | int
它创建
typing.Union
的实例。int | str == typing.Union[int, str] type(int | str) is typing.Union
可选类型可以拼写为与
None
的联合。str | None == typing.Optional[str]
- isinstance(obj, union_object)
- issubclass(obj, union_object)
对联合对象的
isinstance()
和issubclass()
调用也受支持。>>> isinstance("", int | str) True
然而,联合对象中的 参数化泛型 无法被检查。
>>> isinstance(1, int | list[int]) # short-circuit evaluation True >>> isinstance([1], int | list[int]) Traceback (most recent call last): ... TypeError: isinstance() argument 2 cannot be a parameterized generic
联合对象的用户可见类型可以从 typing.Union
访问,并用于 isinstance()
检查。
>>> import typing
>>> isinstance(int | str, typing.Union)
True
>>> typing.Union()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: cannot create 'typing.Union' instances
备注
类型对象的 __or__()
方法是为了支持 X | Y
语法而添加的。如果元类实现了 __or__()
,则 Union 可能会覆盖它。
>>> class M(type):
... def __or__(self, other):
... return "Hello"
...
>>> class C(metaclass=M):
... pass
...
>>> C | int
'Hello'
>>> int | C
int | C
参见
PEP 604 - 提出 X | Y
语法和 Union 类型的 PEP。
在 3.10 版本加入。
版本 3.14 中已更改: Union 对象现在是 typing.Union
的实例。以前,它们是 types.UnionType
的实例,后者仍然是 typing.Union
的别名。
其他内置类型¶
解释器支持多种其他类型的对象。其中大多数只支持一到两个操作。
模块¶
模块的唯一特殊操作是属性访问:m.name
,其中 m 是一个模块,name 访问 m 的符号表中定义的名称。可以为模块属性赋值。(请注意,import
语句严格来说不是对模块对象的操作;import foo
不需要名为 foo 的模块对象存在,而是需要一个在某处定义的(外部)名为 foo 的模块的定义。)
每个模块的一个特殊属性是 __dict__
。这是包含模块符号表的字典。修改此字典实际上会更改模块的符号表,但无法直接为 __dict__
属性赋值(您可以编写 m.__dict__['a'] = 1
,这将定义 m.a
为 1
,但不能编写 m.__dict__ = {}
)。直接修改 __dict__
不推荐。
内置于解释器的模块如下所示:<module 'sys' (built-in)>
。如果从文件加载,则显示为 <module 'os' from '/usr/local/lib/pythonX.Y/os.pyc'>
。
类和类实例¶
函数¶
函数对象通过函数定义创建。函数对象的唯一操作是调用它:func(argument-list)
。
实际上有两种函数对象:内置函数和用户定义函数。两者都支持相同的操作(调用函数),但实现不同,因此对象类型也不同。
有关更多信息,请参阅 函数定义。
方法¶
方法是使用属性表示法调用的函数。有两种:内置方法(例如列表上的 append()
)和类实例方法。内置方法与支持它们的对象类型一起描述。
如果通过实例访问方法(在类命名空间中定义的函数),则会得到一个特殊对象:绑定方法(也称为 实例方法)对象。调用时,它会将 self
参数添加到参数列表中。绑定方法有两个特殊的只读属性:m.__self__
是方法操作的对象,而 m.__func__
是实现该方法的函数。调用 m(arg-1, arg-2, ..., arg-n)
完全等同于调用 m.__func__(m.__self__, arg-1, arg-2, ..., arg-n)
。
与 函数对象 一样,绑定方法对象支持获取任意属性。但是,由于方法属性实际上存储在底层函数对象(method.__func__
)上,因此不允许在绑定方法上设置方法属性。尝试在方法上设置属性会导致引发 AttributeError
。要设置方法属性,您需要显式地在底层函数对象上设置它。
>>> class C:
... def method(self):
... pass
...
>>> c = C()
>>> c.method.whoami = 'my name is method' # can't set on the method
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'method' object has no attribute 'whoami'
>>> c.method.__func__.whoami = 'my name is method'
>>> c.method.whoami
'my name is method'
有关更多信息,请参阅 实例方法。
代码对象¶
代码对象由实现用来表示“伪编译”的可执行 Python 代码,例如函数体。它们与函数对象不同,因为它们不包含对其全局执行环境的引用。代码对象由内置的 compile()
函数返回,并且可以通过函数对象的 __code__
属性提取。另请参阅 code
模块。
访问 __code__
会引发一个带有参数 obj
和 "__code__"
的 审核事件 object.__getattr__
。
可以通过将代码对象(而不是源字符串)传递给 exec()
或 eval()
内置函数来执行或评估它。
有关更多信息,请参阅 标准类型层次结构。
类型对象¶
类型对象表示各种对象类型。对象的类型通过内置函数 type()
访问。类型没有特殊的运算符。标准模块 types
定义了所有标准内置类型的名称。
类型显示如下:<class 'int'>
。
Null 对象¶
此对象由不显式返回值的方法返回。它不支持任何特殊操作。只有一个 Null 对象,名为 None
(内置名称)。type(None)()
会产生相同的单例。
它被写为 None
。
Ellipsis 对象¶
此对象通常用于指示某项被省略。它不支持任何特殊操作。只有一个 Ellipsis 对象,名为 Ellipsis
(内置名称)。type(Ellipsis)()
会产生 Ellipsis
单例。
它被写为 Ellipsis
或 ...
。
在典型用法中,...
作为 Ellipsis
对象出现在几个不同的地方,例如:
作为函数体,而不是 pass 语句。
在第三方库中,例如 NumPy 的切片和步幅。
Python 还在并非 Ellipsis
对象的地方使用三个点,例如:
最后,Python 文档经常使用三个点来表示省略的内容,即使在也使用它们作为 Ellipsis
的代码示例中也是如此。
NotImplemented 对象¶
当比较和二进制运算无法处理不支持的类型时,将返回此对象。有关更多信息,请参阅 比较。存在一个 NotImplemented
对象。 type(NotImplemented)()
会产生单例实例。
它被写为 NotImplemented
。
内部对象¶
特殊属性¶
实现为几个对象类型添加了一些特殊的只读属性(在相关时)。其中一些未在内置函数 dir()
中报告。
- definition.__name__¶
类、函数、方法、描述符或生成器实例的名称。
- definition.__module__¶
定义类或函数的模块的名称。
- definition.__doc__¶
类或函数的文档字符串,如果未定义则为
None
。
整数字符串转换长度限制¶
CPython 有一个全局限制,用于在 int
和 str
之间进行转换,以减轻拒绝服务攻击。此限制*仅*适用于十进制或其他非 2 的幂数制。十六进制、八进制和二进制转换不受限制。该限制是可配置的。
CPython 中的 int
类型是存储在二进制形式中的任意长度数字(通常称为“bignum”)。不存在可以线性时间将字符串转换为二进制整数或将二进制整数转换为字符串的算法,*除非*基数是 2 的幂。即使是最佳已知的十进制算法也具有亚二次复杂度。转换一个大值,例如 int('1' * 500_000)
,在快速 CPU 上可能需要一秒多。
限制转换大小提供了一种实用的方法来避免 CVE 2020-10735。
当非线性转换算法涉及时,限制应用于输入或输出字符串中的数字字符数量。下划线和符号不计入此限制。
当操作会超出限制时,会引发 ValueError
。
>>> import sys
>>> sys.set_int_max_str_digits(4300) # Illustrative, this is the default.
>>> _ = int('2' * 5432)
Traceback (most recent call last):
...
ValueError: Exceeds the limit (4300 digits) for integer string conversion: value has 5432 digits; use sys.set_int_max_str_digits() to increase the limit
>>> i = int('2' * 4300)
>>> len(str(i))
4300
>>> i_squared = i*i
>>> len(str(i_squared))
Traceback (most recent call last):
...
ValueError: Exceeds the limit (4300 digits) for integer string conversion; use sys.set_int_max_str_digits() to increase the limit
>>> len(hex(i_squared))
7144
>>> assert int(hex(i_squared), base=16) == i*i # Hexadecimal is unlimited.
默认限制为 4300 位数字,如 sys.int_info.default_max_str_digits
中所示。可配置的最低限制为 640 位数字,如 sys.int_info.str_digits_check_threshold
中所示。
验证
>>> import sys
>>> assert sys.int_info.default_max_str_digits == 4300, sys.int_info
>>> assert sys.int_info.str_digits_check_threshold == 640, sys.int_info
>>> msg = int('578966293710682886880994035146873798396722250538762761564'
... '9252925514383915483333812743580549779436104706260696366600'
... '571186405732').to_bytes(53, 'big')
...
在 3.11 版本中新增。
受影响的 API¶
该限制仅适用于 int
和 str
或 bytes
之间可能耗时的转换。
int(string)
,默认基数为 10。int(string, base)
,对于所有不是 2 的幂的基数。str(integer)
.repr(integer)
.任何其他转换为十进制的字符串,例如
f"{integer}"
、"{}".format(integer)
或b"%d" % integer
。
这些限制不适用于具有线性算法的函数。
int(string, base)
,基数为 2、4、8、16 或 32。格式规范迷你语言,用于十六进制、八进制和二进制数字。
配置限制¶
在 Python 启动之前,您可以使用环境变量或解释器命令行标志来配置限制。
PYTHONINTMAXSTRDIGITS
,例如PYTHONINTMAXSTRDIGITS=640 python3
将限制设置为 640,或PYTHONINTMAXSTRDIGITS=0 python3
来禁用此限制。-X int_max_str_digits
,例如python3 -X int_max_str_digits=640
sys.flags.int_max_str_digits
包含PYTHONINTMAXSTRDIGITS
或-X int_max_str_digits
的值。如果同时设置了环境变量和-X
选项,则-X
选项具有优先权。值为 -1 表示两者都未设置,因此在初始化期间使用了sys.int_info.default_max_str_digits
的值。
从代码中,您可以使用这些 sys
API 来检查当前限制并设置新的限制。
sys.get_int_max_str_digits()
和sys.set_int_max_str_digits()
分别是解释器范围内的限制的getter和setter。子解释器有自己的限制。
有关默认值和最小值的信息可以在 sys.int_info
中找到。
sys.int_info.default_max_str_digits
是编译时默认限制。sys.int_info.str_digits_check_threshold
是限制的最低可接受值(0 除外,它会禁用它)。
在 3.11 版本中新增。
注意
设置低限制*可能*会导致问题。虽然罕见,但存在一些代码在其源中使用十进制整数常量,这些常量超过了最小阈值。设置限制的一个后果是,包含长于限制的十进制整数文字的 Python 源代码将在解析过程中遇到错误,通常是在启动或导入时,甚至在安装时 - 任何时候不存在现有 .pyc
文件都会出现此问题。包含此类大型常量的源代码的解决方法是将其转换为 0x
十六进制形式,因为它没有限制。
如果您使用低限制,请彻底测试您的应用程序。确保您的测试在通过环境变量或标志早期设置的限制下运行,以便它在启动时甚至在可能调用 Python 来预编译 .py
源文件到 .pyc
文件的任何安装步骤中都适用。
推荐配置¶
大多数应用程序都期望 sys.int_info.default_max_str_digits
的默认值是合理的。如果您的应用程序需要不同的限制,请从主入口点使用与 Python 版本无关的代码进行设置,因为这些 API 在 3.12 之前的版本中的安全补丁版本中已添加。
示例
>>> import sys
>>> if hasattr(sys, "set_int_max_str_digits"):
... upper_bound = 68000
... lower_bound = 4004
... current_limit = sys.get_int_max_str_digits()
... if current_limit == 0 or current_limit > upper_bound:
... sys.set_int_max_str_digits(upper_bound)
... elif current_limit < lower_bound:
... sys.set_int_max_str_digits(lower_bound)
如果您需要完全禁用它,请将其设置为 0
。
脚注