内置类型¶
以下章节描述了解释器内置的标准类型。
主要的内置类型有数字、序列、映射、类、实例和异常。
一些集合类是可变的。原地添加、删除或重新排列其成员,并且不返回特定项的方法,永远不会返回集合实例本身,而是返回 None
。
一些操作由多个对象类型支持;特别是,实际上所有对象都可以比较是否相等、测试真值,并转换为字符串(使用 repr()
函数或略有不同的 str()
函数)。当对象被 print()
函数写入时,会隐式使用后一个函数。
真值检测¶
任何对象都可以进行真值测试,以便在 if
或 while
条件中使用,或者作为以下布尔运算的操作数。
默认情况下,一个对象被认为是真,除非它的类定义了一个 __bool__()
方法返回 False
或一个 __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'
附加到数字文字会产生一个虚数(实部为零的复数),您可以将其添加到整数或浮点数以获得具有实部和虚部的复数。
Python 完全支持混合算术:当二元算术运算符具有不同数值类型的操作数时,类型较“窄”的操作数会扩展到另一个操作数的类型,其中整数比浮点数窄,浮点数比复数窄。不同类型数字之间的比较行为就像比较这些数字的精确值一样。[2]
构造函数 int()
、float()
和 complex()
可用于生成特定类型的数字。
所有数值类型(复数除外)都支持以下操作(有关操作的优先级,请参阅 运算符优先级)
运算 |
结果 |
备注 |
完整文档 |
---|---|---|---|
|
x 和 y 的和 |
||
|
x 和 y 的差 |
||
|
x 和 y 的乘积 |
||
|
x 和 y 的商 |
||
|
x 和 y 的向下取整的商 |
(1)(2) |
|
|
|
(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 必须是 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
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 还有以下附加方法。
- 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
是一个十进制整数,带有可选的前导符号。大小写不重要,并且整数或小数部分中必须至少有一个十六进制数字。此语法类似于 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'
数值类型的哈希¶
对于数字 x
和 y
,可能具有不同的类型,要求当 x == y
时,始终有 hash(x) == hash(y)
(有关更多详细信息,请参阅 __hash__()
方法文档)。为了在各种数值类型(包括 int
,float
,decimal.Decimal
和 fractions.Fraction
)中易于实现和提高效率,Python 的数值类型哈希基于单个数学函数,该函数定义为任何有理数,因此适用于 int
和 fractions.Fraction
的所有实例,以及 float
和 decimal.Decimal
的所有有限实例。本质上,此函数由对固定素数 P
取模的简化给出。P
的值作为 modulus
属性提供给 Python,该属性是 sys.hash_info
的一部分。
CPython 实现细节: 当前,使用的素数在具有 32 位 C 长整数的机器上为 P = 2**31 - 1
,在具有 64 位 C 长整数的机器上为 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) |
|
从 i 到 j 的 s 的切片 |
(3)(4) |
|
从 i 到 j,步长为 k 的 s 的切片 |
(3)(5) |
|
s 的长度 |
|
|
s 的最小项 |
|
|
s 的最大项 |
|
|
x 在 s 中第一次出现的索引(在索引 i 或之后且在索引 j 之前) |
(8) |
|
x 在 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 或 i 为None
,则使用0
。如果省略 j 或 j 为None
,则使用len(s)
。如果 i 大于或等于 j,则切片为空。从 i 到 j,步长为 k 的 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
)仅支持遵循特定模式的项序列,因此不支持序列连接或重复。当在 s 中找不到 x 时,
index
会引发ValueError
。并非所有实现都支持传递附加参数 i 和 j。这些参数允许高效地搜索序列的子部分。传递额外的参数大致相当于使用s[i:j].index(x)
,只是不复制任何数据,并且返回的索引相对于序列的开头而不是切片的开头。
不可变序列类型¶
不可变序列类型通常实现的唯一操作(可变序列类型也未实现的操作)是对 hash()
内置函数的支持。
这种支持允许将不可变序列(例如 tuple
实例)用作 dict
键,并存储在 set
和 frozenset
实例中。
尝试哈希包含不可哈希值的不可变序列将导致 TypeError
。
可变序列类型¶
下表中的操作定义在可变序列类型上。提供了 collections.abc.MutableSequence
ABC,以便更容易地在自定义序列类型上正确实现这些操作。
在表中,s 是一个可变序列类型的实例,t 是任何可迭代对象,x 是一个任意对象,它满足 s 施加的任何类型和值限制(例如,bytearray
只接受满足值限制 0 <= x <= 255
的整数)。
运算 |
结果 |
备注 |
---|---|---|
|
s 的第 i 项被 x 替换 |
|
|
s 中从 i 到 j 的切片被可迭代对象 t 的内容替换 |
|
|
与 |
|
|
|
(1) |
|
从列表中删除 |
|
|
将 x 追加到序列的末尾(与 |
|
|
删除 s 中的所有项(与 |
(5) |
|
创建 s 的浅拷贝(与 |
(5) |
|
使用 t 的内容扩展 s(在大多数情况下与 |
|
|
用其内容重复 n 次来更新 s |
(6) |
|
在 i 给定的索引处将 x 插入到 s 中(与 |
|
|
检索索引 i 处的项,并将其从 s 中删除 |
(2) |
|
从 s 中删除第一个 |
(3) |
|
就地反转 s 的项 |
(4) |
备注
如果 k 不等于
1
,则 t 的长度必须与它替换的切片长度相同。可选参数 i 默认为
-1
,因此默认情况下,删除并返回最后一项。当在 s 中未找到 x 时,
remove()
引发ValueError
。当反转大序列时,为了节省空间,
reverse()
方法就地修改序列。为了提醒用户它通过副作用操作,它不返回反转后的序列。包含
clear()
和copy()
是为了与不支持切片操作的可变容器(如dict
和set
)的接口保持一致。copy()
不是collections.abc.MutableSequence
ABC 的一部分,但大多数具体的列表类都提供了它。3.3 版本新增:
clear()
和copy()
方法。值 n 是一个整数,或者是一个实现
__index__()
的对象。 n 的零值和负值会清除序列。序列中的项不会被复制;它们会被多次引用,如 通用序列操作 中s * n
所述。
列表¶
列表是可变序列,通常用于存储同类项的集合(其中相似程度的确切程度会因应用程序而异)。
- 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])
range 构造函数的参数必须是整数(可以是内置的
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
)
与常规的 list
或 tuple
相比,range
类型的优势在于,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 版本中更改: 实现序列 ABC。支持切片和负索引。以恒定时间测试 int
对象是否为成员,而不是遍历所有项目。
另请参阅
linspace 配方 展示了如何实现一个适用于浮点数应用的 range 惰性版本。
文本序列类型 — str
¶
Python 中的文本数据使用 str
对象或字符串来处理。字符串是 Unicode 代码点的不可变序列。字符串字面值可以使用多种方式书写
单引号:
'允许嵌入 "双" 引号'
双引号:
"允许嵌入 '单' 引号"
三引号:
'''三个 单 引号'''
,"""三个 双 引号"""
三引号字符串可以跨越多行 - 所有相关的空白符都将包含在字符串字面值中。
属于单个表达式一部分且彼此之间只有空白符的字符串字面值将被隐式转换为单个字符串字面值。也就是说, ("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(object='')¶
- class str(object=b'', encoding='utf-8', errors='strict')
返回 *object* 的 字符串 版本。如果未提供 *object*,则返回空字符串。否则,
str()
的行为取决于是否给出了 *encoding* 或 *errors*,如下所示。如果既未给出 *encoding* 也未给出 *errors*,则
str(object)
返回type(object).__str__(object)
,它是 *object* 的“非正式”或格式良好的可打印字符串表示形式。对于字符串对象,这是字符串本身。如果 *object* 没有__str__()
方法,则str()
将回退到返回repr(object)
。如果给出了 *encoding* 或 *errors* 中的至少一个,则 *object* 应该是一个 bytes-like object (例如
bytes
或bytearray
)。在这种情况下,如果 *object* 是一个bytes
(或bytearray
)对象,则str(bytes, encoding, errors)
等效于bytes.decode(encoding, errors)
。否则,在调用bytes.decode()
之前,将获取缓冲区对象的基础字节对象。有关缓冲区对象的信息,请参阅二进制序列类型 — bytes、bytearray、memoryview 和 缓冲区协议。将
bytes
对象传递给没有 *encoding* 或 *errors* 参数的str()
属于返回非正式字符串表示形式的第一种情况(另请参阅 Python 的-b
命令行选项)。例如>>> str(b'Zoot!') "b'Zoot!'"
有关
str
类及其方法的更多信息,请参阅文本序列类型 — str 和下面的字符串方法部分。要输出格式化的字符串,请参阅 f-字符串 和 格式字符串语法 部分。此外,请参阅文本处理服务部分。
字符串方法¶
字符串实现了所有通用序列操作,以及下面描述的其他方法。
字符串还支持两种字符串格式化风格,一种提供了高度的灵活性和自定义功能(请参阅 str.format()
、格式字符串语法 和 自定义字符串格式化),另一种基于 C printf
样式格式化,它处理的类型范围较窄且使用起来稍微困难一些,但对于它可以处理的情况,通常速度更快 (printf 样式的字符串格式化)。
标准库的文本处理服务部分涵盖了许多其他模块,这些模块提供了各种与文本相关的实用程序(包括 re
模块中的正则表达式支持)。
- str.capitalize()¶
返回字符串的副本,其中第一个字符大写,其余字符小写。
在 3.8 版本中更改: 现在,第一个字符将转换为首字母大写,而不是大写。这意味着像连字这样的字符将只将其首字母大写,而不是整个字符。
- str.casefold()¶
返回字符串的 casefolded 副本。Casefolded 字符串可用于不区分大小写的匹配。
Casefolding 类似于小写,但更激进,因为它旨在消除字符串中的所有大小写差异。例如,德语小写字母
'ß'
等效于"ss"
。由于它已经是小写,lower()
对'ß'
无效;casefold()
会将其转换为"ss"
。大小写折叠算法在Unicode 标准的第 3.13 节“默认大小写折叠”中描述。
3.3 版本中新增。
- str.center(width[, fillchar])¶
返回长度为 *width* 的字符串中居中的字符串。使用指定的 *fillchar* 进行填充(默认为 ASCII 空格)。如果 *width* 小于或等于
len(s)
,则返回原始字符串。
- str.count(sub[, start[, end]])¶
返回子字符串 *sub* 在范围 [*start*, *end*] 内的非重叠出现次数。可选参数 *start* 和 *end* 的解释方式与切片表示法中相同。
如果 sub 为空,则返回字符之间空字符串的数量,该数量等于字符串的长度加一。
- str.encode(encoding='utf-8', errors='strict')¶
返回以
bytes
编码的字符串。encoding 默认为
'utf-8'
;有关可能的值,请参阅 标准编码。errors 控制如何处理编码错误。 如果是
'strict'
(默认值),则会引发UnicodeError
异常。其他可能的值包括'ignore'
、'replace'
、'xmlcharrefreplace'
、'backslashreplace'
以及通过codecs.register_error()
注册的任何其他名称。 有关详细信息,请参阅 错误处理程序。出于性能原因,除非实际发生编码错误、启用 Python 开发模式 或使用 调试版本,否则不会检查 errors 值的有效性。
在 3.1 版本中更改: 增加了对关键字参数的支持。
在 3.9 版本中更改: 现在,在 Python 开发模式 和 调试模式 下检查 errors 参数的值。
- str.endswith(suffix[, start[, end]])¶
如果字符串以指定的 suffix 结尾,则返回
True
,否则返回False
。suffix 也可以是要查找的后缀元组。使用可选的 start,从该位置开始测试。使用可选的 end,在该位置停止比较。
- str.expandtabs(tabsize=8)¶
返回字符串的副本,其中所有制表符都替换为一个或多个空格,具体取决于当前列和给定的制表符大小。制表符位置每隔 tabsize 个字符出现一次(默认为 8,制表符位置位于列 0、8、16 等)。要展开字符串,当前列设置为零,并逐个字符地检查字符串。如果字符是制表符 (
\t
),则在结果中插入一个或多个空格字符,直到当前列等于下一个制表符位置。(制表符本身不复制。)如果字符是换行符 (\n
) 或回车符 (\r
),则复制该字符,并将当前列重置为零。任何其他字符都保持不变地复制,并且当前列递增 1,而与打印时字符的表示方式无关。>>> '01\t012\t0123\t01234'.expandtabs() '01 012 0123 01234' >>> '01\t012\t0123\t01234'.expandtabs(4) '01 012 0123 01234'
- str.find(sub[, start[, end]])¶
返回字符串中子字符串 sub 在切片
s[start:end]
中找到的最低索引。可选参数 start 和 end 的解释方式与切片表示法相同。如果未找到 sub,则返回-1
。
- str.format(*args, **kwargs)¶
执行字符串格式化操作。调用此方法的字符串可以包含由大括号
{}
分隔的文本或替换字段。每个替换字段都包含位置参数的数字索引,或关键字参数的名称。返回字符串的副本,其中每个替换字段都替换为相应参数的字符串值。>>> "The sum of 1 + 2 is {0}".format(1+2) 'The sum of 1 + 2 is 3'
有关可以在格式字符串中指定的各种格式化选项的说明,请参阅 格式字符串语法。
注意
当使用
n
类型(例如:'{:n}'.format(1234)
)格式化数字(int
、float
、complex
、decimal.Decimal
和子类)时,如果localeconv()
的decimal_point
和thousands_sep
字段是非 ASCII 或长度超过 1 个字节,并且LC_NUMERIC
区域设置与LC_CTYPE
区域设置不同,则该函数会将LC_CTYPE
区域设置临时设置为LC_NUMERIC
区域设置以解码它们。此临时更改会影响其他线程。在 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
。如果以下之一返回True
,则字符c
为字母数字:c.isalpha()
、c.isdecimal()
、c.isdigit()
或c.isnumeric()
。
- str.isalpha()¶
如果字符串中的所有字符都是字母,并且至少有一个字符,则返回
True
,否则返回False
。字母字符是在 Unicode 字符数据库中定义为“字母”的字符,即通用类别属性为“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,五分之一。形式上,数值字符是具有属性值 Numeric_Type=Digit、Numeric_Type=Decimal 或 Numeric_Type=Numeric 的字符。
- str.isprintable()¶
如果字符串中的所有字符都是可打印的,或者字符串为空,则返回
True
,否则返回False
。不可打印的字符是在 Unicode 字符数据库中定义为“其他”或“分隔符”的字符,但 ASCII 空格 (0x20) 除外,它被认为是可打印的。(请注意,此上下文中的可打印字符是指在对字符串调用repr()
时不应转义的字符。这与写入sys.stdout
或sys.stderr
的字符串的处理无关。)
- str.isspace()¶
如果字符串中只有空白字符,并且至少有一个字符,则返回
True
,否则返回False
。如果一个字符在 Unicode 字符数据库中(请参阅
unicodedata
),其通用类别为Zs
(“分隔符,空格”),或者其双向类为WS
、B
或S
,则该字符是空白字符。
- str.istitle()¶
如果该字符串是首字母大写的字符串,并且至少有一个字符,则返回
True
,例如,大写字符只能跟在未带大小写的字符之后,而小写字符只能跟在带大小写的字符之后。否则返回False
。
- 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.lower()¶
返回字符串的副本,其中所有带大小写的字符[4] 都转换为小写。
所使用的小写算法在 Unicode 标准的第 3.13 节“默认大小写折叠”中描述。
- str.lstrip([chars])¶
返回删除前导字符的字符串的副本。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(x[, y[, z]])¶
这个静态方法返回一个可用于
str.translate()
的转换表。如果只有一个参数,它必须是一个字典,将 Unicode 序号(整数)或字符(长度为 1 的字符串)映射到 Unicode 序号、字符串(任意长度)或
None
。字符键随后会被转换为序号。如果有两个参数,它们必须是长度相等的字符串,并且在生成的字典中,x 中的每个字符都会被映射到 y 中相同位置的字符。 如果有第三个参数,它必须是一个字符串,其字符将在结果中被映射到
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])¶
返回一个删除了尾随字符的字符串副本。 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']
- str.splitlines(keepends=False)¶
返回字符串中的行列表,在行边界处断开。 除非给出了 keepends 且为 true,否则行分隔符不包含在结果列表中。
此方法会在以下行边界处进行分割。 特别地,这些边界是 通用换行符 的超集。
表示
描述
\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])¶
返回删除前导和尾随字符的字符串的副本。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."
- str.translate(table)¶
返回字符串的副本,其中每个字符都已通过给定的转换表映射。该表必须是一个通过
__getitem__()
实现索引的对象,通常是 映射 或 序列。当使用 Unicode 序号(整数)进行索引时,表对象可以执行以下任何操作:返回 Unicode 序号或字符串,以将字符映射到一个或多个其他字符;返回None
,以从返回的字符串中删除字符;或引发LookupError
异常,以将字符映射到其自身。你可以使用
str.maketrans()
从不同格式的字符到字符的映射创建转换映射。另请参阅
codecs
模块,以获得更灵活的自定义字符映射方法。
- str.upper()¶
返回字符串的副本,其中所有带大小写的字符 [4] 都转换为大写。请注意,如果
s
包含不带大小写的字符,或者如果结果字符的 Unicode 类别不是“Lu”(字母,大写),而是例如“Lt”(字母,标题),则s.upper().isupper()
可能是False
。使用的大写算法在 Unicode 标准的 3.13 节“默认大小写折叠”中进行了描述。
- str.zfill(width)¶
返回一个字符串的副本,该字符串的左侧填充了 ASCII
'0'
数字,以生成长度为 width 的字符串。前导符号前缀('+'
/'-'
)的处理方式是在符号字符之后而不是之前插入填充。如果 width 小于或等于len(s)
,则返回原始字符串。例如
>>> "42".zfill(5) '00042' >>> "-42".zfill(5) '-0042'
printf
样式字符串格式化¶
注意
此处描述的格式化操作显示了各种怪癖,这些怪癖会导致许多常见错误(例如,未能正确显示元组和字典)。使用较新的 格式化字符串字面量,str.format()
接口或 模板字符串 可以帮助避免这些错误。这些替代方案中的每一个都提供了它们自己的简单性、灵活性和/或可扩展性的权衡和好处。
字符串对象有一个唯一的内置操作:%
运算符(取模)。这也称为字符串格式化或插值运算符。给定 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.
在这种情况下,格式中可能不会出现 *
说明符(因为它们需要顺序参数列表)。
转换标志字符是:
标志 |
含义 |
---|---|
|
值转换将使用“替代形式”(如下定义)。 |
|
数值将使用零填充进行转换。 |
|
转换后的值将左对齐(如果同时给定,则覆盖 |
|
(空格)在有符号转换产生的正数(或空字符串)之前应保留一个空格。 |
|
符号字符( |
长度修饰符(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[, encoding[, errors]]])¶
首先,字节字面量的语法与字符串字面量的语法大致相同,只不过添加了
b
前缀单引号:
b'仍然允许嵌入"双引号"'
双引号:
b"仍然允许嵌入'单引号'"
三引号:
b'''3 个单引号'''
,b"""3 个双引号"""
字节字面量中仅允许 ASCII 字符(无论声明的源代码编码如何)。任何超过 127 的二进制值都必须使用适当的转义序列输入到字节字面量中。
与字符串字面量一样,字节字面量也可以使用
r
前缀来禁用转义序列的处理。有关各种形式的字节字面量(包括支持的转义序列)的更多信息,请参阅 字符串和字节字面量。虽然字节字面量和表示形式基于 ASCII 文本,但字节对象的行为实际上类似于整数的不可变序列,序列中的每个值都受到限制,使得
0 <= x < 256
(尝试违反此限制将触发ValueError
)。这样做是为了强调,虽然许多二进制格式包含基于 ASCII 的元素,并且可以使用一些面向文本的算法进行有用的操作,但这对于任意二进制数据来说通常不是这种情况(盲目地将文本处理算法应用于与 ASCII 不兼容的二进制数据格式通常会导致数据损坏)。除了字面形式之外,还可以通过多种其他方式创建字节对象
指定长度的零填充字节对象:
bytes(10)
从整数的可迭代对象中:
bytes(range(20))
通过缓冲区协议复制现有二进制数据:
bytes(obj)
另请参阅 bytes 内置函数。
由于 2 个十六进制数字恰好对应一个字节,因此十六进制数字是描述二进制数据的常用格式。因此,字节类型有一个额外的类方法来读取该格式的数据
- classmethod fromhex(string)¶
这个
bytes
类方法返回一个字节对象,解码给定的字符串对象。该字符串必须包含每个字节两个十六进制数字,并忽略 ASCII 空白。>>> bytes.fromhex('2Ef0 F1f2 ') b'.\xf0\xf1\xf2'
在 3.7 版本中更改:
bytes.fromhex()
现在跳过字符串中的所有 ASCII 空白,而不仅仅是空格。
存在反向转换函数,可以将字节对象转换为其十六进制表示形式。
- hex([sep[, bytes_per_sep]])¶
返回一个字符串对象,其中包含实例中每个字节的两个十六进制数字。
>>> 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 参数,以在十六进制输出中的字节之间插入分隔符。
由于 bytes 对象是整数序列(类似于元组),对于 bytes 对象 b,b[0]
将是一个整数,而 b[0:1]
将是一个长度为 1 的 bytes 对象。(这与文本字符串形成对比,在文本字符串中,索引和切片都将产生长度为 1 的字符串)
bytes 对象的表示形式使用字面量格式(b'...'
),因为它通常比例如 bytes([46, 46, 46])
更实用。 你始终可以使用 list(b)
将 bytes 对象转换为整数列表。
Bytearray 对象¶
- class bytearray([source[, encoding[, errors]]])¶
bytearray 对象没有专门的字面量语法,它们始终通过调用构造函数来创建
创建空实例:
bytearray()
创建具有给定长度的零填充实例:
bytearray(10)
从整数的可迭代对象创建:
bytearray(range(20))
通过缓冲区协议复制现有二进制数据:
bytearray(b'Hi!')
由于 bytearray 对象是可变的,它们除了 Bytes 和 Bytearray 操作 中描述的常见 bytes 和 bytearray 操作之外,还支持 可变 序列操作。
另请参阅 bytearray 内置函数。
由于 2 位十六进制数字恰好对应一个字节,十六进制数字是描述二进制数据常用的格式。因此,bytearray 类型有一个额外的类方法来读取该格式的数据
- classmethod fromhex(string)¶
这个
bytearray
类方法返回 bytearray 对象,解码给定的字符串对象。该字符串必须包含每个字节的两位十六进制数字,并忽略 ASCII 空白符。>>> bytearray.fromhex('2Ef0 F1f2 ') bytearray(b'.\xf0\xf1\xf2')
在 3.7 版本中更改:
bytearray.fromhex()
现在跳过字符串中的所有 ASCII 空白符,而不仅仅是空格。
存在一个反向转换函数,用于将 bytearray 对象转换为其十六进制表示形式。
- hex([sep[, bytes_per_sep]])¶
返回一个字符串对象,其中包含实例中每个字节的两个十六进制数字。
>>> bytearray(b'\xf0\xf1\xf2').hex() 'f0f1f2'
在 3.5 版本中添加。
在 3.8 版本中更改: 类似于
bytes.hex()
,bytearray.hex()
现在支持可选的 sep 和 bytes_per_sep 参数,以在十六进制输出中的字节之间插入分隔符。
由于 bytearray 对象是整数序列(类似于列表),对于 bytearray 对象 b,b[0]
将是一个整数,而 b[0:1]
将是一个长度为 1 的 bytearray 对象。(这与文本字符串形成对比,在文本字符串中,索引和切片都将产生长度为 1 的字符串)
bytearray 对象的表示形式使用 bytes 字面量格式(bytearray(b'...')
),因为它通常比例如 bytearray([46, 46, 46])
更实用。你始终可以使用 list(b)
将 bytearray 对象转换为整数列表。
Bytes 和 Bytearray 操作¶
bytes 和 bytearray 对象都支持常见的 序列操作。它们不仅与相同类型的操作数相互操作,而且还与任何 类字节对象 相互操作。由于这种灵活性,它们可以在操作中自由混合而不会导致错误。但是,结果的返回类型可能取决于操作数的顺序。
注意
bytes 和 bytearray 对象的方法不接受字符串作为它们的参数,就像字符串的方法不接受 bytes 作为它们的参数一样。例如,你必须编写
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]])¶
返回在 [start, end] 范围内子序列 sub 的非重叠出现次数。可选参数 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()
注册的任何其他名称。有关详细信息,请参阅 错误处理程序。出于性能考虑,除非实际发生解码错误,否则不会检查 errors 的值的有效性,或者启用了 Python 开发模式,或者使用了 调试构建。
注意
将 encoding 参数传递给
str
允许直接解码任何 bytes-like 对象,而无需创建临时的bytes
或bytearray
对象。在 3.1 版本中更改: 增加了对关键字参数的支持。
在 3.9 版本中更改: 现在,在 Python 开发模式 和 调试模式 下检查 errors 参数的值。
- bytes.endswith(suffix[, start[, end]])¶
- bytearray.endswith(suffix[, start[, end]])¶
如果二进制数据以指定的 suffix 结尾,则返回
True
,否则返回False
。suffix 也可以是要查找的后缀的元组。使用可选的 start,从该位置开始测试。使用可选的 end,在该位置停止比较。要搜索的后缀可以是任何 bytes-like 对象。
- 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)¶
返回一个字节或字节数组对象,它是 iterable 中二进制数据序列的连接。如果 iterable 中有任何值不是 bytes-like 对象,包括
str
对象,则会引发TypeError
。元素之间的分隔符是提供此方法的字节或字节数组对象的内容。
- static bytes.maketrans(from, to)¶
- static bytearray.maketrans(from, to)¶
此静态方法返回一个可用于
bytes.translate()
的转换表,该表会将 from 中的每个字符映射到 to 中相同位置的字符;from 和 to 都必须是 bytes-like 对象 且具有相同的长度。在 3.1 版本中新增。
- bytes.partition(sep)¶
- bytearray.partition(sep)¶
在第一次出现 sep 时拆分序列,并返回一个包含分隔符之前的部分、分隔符本身或其字节数组副本以及分隔符之后的部分的 3 元组。如果未找到分隔符,则返回一个包含原始序列副本、后跟两个空字节或字节数组对象的 3 元组。
要搜索的分隔符可以是任何 bytes-like 对象。
- bytes.replace(old, new[, count])¶
- bytearray.replace(old, new[, count])¶
返回序列的副本,其中子序列 old 的所有出现都被 new 替换。如果给出了可选参数 count,则仅替换前 count 次出现。
要搜索的子序列及其替换可以是任何 bytes-like 对象。
注意
此方法的 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 的位置分割序列,并返回一个 3 元组,其中包含分隔符之前的部分、分隔符本身或其 bytearray 副本以及分隔符之后的部分。如果未找到分隔符,则返回一个 3 元组,其中包含两个空的 bytes 或 bytearray 对象,后跟原始序列的副本。
要搜索的分隔符可以是任何 bytes-like 对象。
- bytes.startswith(prefix[, start[, end]])¶
- bytearray.startswith(prefix[, start[, end]])¶
如果二进制数据以指定的 prefix 开头,则返回
True
,否则返回False
。prefix 也可以是要查找的前缀的元组。使用可选的 start,从该位置开始测试。使用可选的 end,在该位置停止比较。要搜索的前缀可以是任何 bytes-like object。
- 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])¶
- bytearray.center(width[, fillbyte])¶
返回在长度为 width 的序列中居中的对象的副本。填充使用指定的 fillbyte 完成(默认为 ASCII 空格)。对于
bytes
对象,如果 width 小于或等于len(s)
,则返回原始序列。注意
此方法的 bytearray 版本 *不* 在原地操作 - 它总是产生一个新对象,即使没有进行任何更改。
- bytes.ljust(width[, fillbyte])¶
- bytearray.ljust(width[, fillbyte])¶
返回在长度为 width 的序列中左对齐的对象的副本。填充使用指定的 fillbyte 完成(默认为 ASCII 空格)。对于
bytes
对象,如果 width 小于或等于len(s)
,则返回原始序列。注意
此方法的 bytearray 版本 *不* 在原地操作 - 它总是产生一个新对象,即使没有进行任何更改。
- bytes.lstrip([chars])¶
- bytearray.lstrip([chars])¶
返回删除指定前导字节的序列的副本。chars 参数是一个二进制序列,指定要删除的字节值集 - 该名称指的是此方法通常与 ASCII 字符一起使用的事实。如果省略或为
None
,则 chars 参数默认为删除 ASCII 空格。chars 参数不是前缀;而是,其值的所有组合都会被剥离>>> b' spacious '.lstrip() b'spacious ' >>> b'www.example.com'.lstrip(b'cmowz.') b'example.com'
要删除的字节值的二进制序列可以是任何 bytes-like object。有关将删除单个前缀字符串而不是一组字符的所有字符的方法,请参阅
removeprefix()
。例如>>> b'Arthur: three!'.lstrip(b'Arthur: ') b'ee!' >>> b'Arthur: three!'.removeprefix(b'Arthur: ') b'three!'
注意
此方法的 bytearray 版本 *不* 在原地操作 - 它总是产生一个新对象,即使没有进行任何更改。
- bytes.rjust(width[, fillbyte])¶
- bytearray.rjust(width[, fillbyte])¶
返回在长度为 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([chars])¶
- bytearray.rstrip([chars])¶
返回一个删除了指定尾部字节的序列副本。chars 参数是一个二进制序列,指定要删除的字节值集合 - 名称指的是此方法通常与 ASCII 字符一起使用的事实。如果省略或为
None
,则 chars 参数默认为删除 ASCII 空白字符。chars 参数不是后缀;而是删除其值的所有组合。>>> 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([chars])¶
- bytearray.strip([chars])¶
返回一个删除了指定前导和尾随字节的序列副本。chars 参数是一个二进制序列,指定要删除的字节值集合 - 名称指的是此方法通常与 ASCII 字符一起使用的事实。如果省略或为
None
,则 chars 参数默认为删除 ASCII 空白字符。chars 参数不是前缀或后缀;而是删除其值的所有组合。>>> 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'
),则会复制它并将当前列重置为零。无论字节值在打印时如何表示,都将复制任何其他字节值且当前列递增 1。>>> 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* 并为真,否则换行符不包含在结果列表中。
例如
>>> 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']
与
split()
不同,当给出分隔符字符串 *sep* 时,此方法为空字符串返回一个空列表,并且终端换行符不会导致额外的行>>> 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
/bytearray
)具有一个独特的内置操作:%
运算符(模)。这也称为字节*格式化*或*插值*运算符。给定 format % values
(其中 *format* 是一个字节对象),*format* 中的 %
转换说明符将替换为 *values* 的零个或多个元素。效果类似于在 C 语言中使用 sprintf()
。
如果 *format* 需要单个参数,则 *values* 可以是单个非元组对象。[5] 否则,*values* 必须是一个元组,其项目数与格式字节对象指定的项目数完全相同,或者是一个映射对象(例如,字典)。
转换说明符包含两个或多个字符,并具有以下组成部分,这些组成部分必须按此顺序出现:
字符
'%'
,它标记说明符的开始。映射键(可选),由带括号的字符序列组成(例如,
(somename)
)。转换标志(可选),它会影响某些转换类型的结果。
最小字段宽度(可选)。如果指定为
'*'
(星号),则实际宽度从 values 中的元组的下一个元素读取,并且要转换的对象位于最小字段宽度和可选精度之后。精度(可选),以
'.'
(点)后跟精度给出。如果指定为'*'
(星号),则实际精度从 values 中的元组的下一个元素读取,并且要转换的值位于精度之后。长度修饰符(可选)。
转换类型。
当右侧参数是字典(或其他映射类型)时,字节对象中的格式*必须*包含一个带括号的映射键,该键紧接在 '%'
字符之后插入到该字典中。映射键从映射中选择要格式化的值。例如
>>> print(b'%(language)s has %(number)03d quote types.' %
... {b'language': b"Python", b"number": 2})
b'Python has 002 quote types.'
在这种情况下,格式中可能不会出现 *
说明符(因为它们需要顺序参数列表)。
转换标志字符是:
标志 |
含义 |
---|---|
|
值转换将使用“替代形式”(如下定义)。 |
|
数值将使用零填充进行转换。 |
|
转换后的值将左对齐(如果同时给定,则覆盖 |
|
(空格)在有符号转换产生的正数(或空字符串)之前应保留一个空格。 |
|
符号字符( |
长度修饰符(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 - 将 % 格式添加到字节和 bytearray
在 3.5 版本中添加。
内存视图¶
memoryview
对象允许 Python 代码访问支持 缓冲区协议 的对象的内部数据,而无需复制。
- class memoryview(object)¶
创建一个引用 *object* 的
memoryview
。*object* 必须支持缓冲区协议。支持缓冲区协议的内置对象包括bytes
和bytearray
。memoryview
具有*元素*的概念,它是原始 *object* 处理的原子内存单元。对于许多简单类型(如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 现在可以使用整数元组进行索引。
memoryview
有几个方法-
__eq__
(exporter
)¶ 如果 memoryview 和 PEP 3118 导出器的形状等效,并且当使用
struct
语法解释操作数的各自格式代码时,所有对应的值都相等,则它们相等。对于
struct
当前支持的格式字符串的子集,tolist()
,如果v.tolist() == w.tolist()
,则v
和w
相等。>>> 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
请注意,与浮点数一样,对于 memoryview 对象,
v is w
不 意味着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
([sep
[,bytes_per_sep
]])¶ 返回一个字符串对象,其中包含缓冲区中每个字节的两个十六进制数字。
>>> 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
[,shape
])¶ 将 memoryview 转换为新的格式或形状。 shape 默认为
[byte_length//new_itemsize]
,这意味着结果视图将是一维的。 返回值是一个新的 memoryview,但缓冲区本身不会被复制。 支持的转换是 1D -> C-连续 和 C-连续 -> 1D。目标格式限定为
struct
语法中的单个元素原生格式。其中一种格式必须是字节格式(‘B’、‘b’ 或 ‘c’)。结果的字节长度必须与原始长度相同。请注意,所有字节长度可能取决于操作系统。将 1D/long 类型转换为 1D/无符号字节类型
>>> 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/无符号字节类型转换为 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/字节类型转换为 3D/整数类型,再转换为 1D/有符号 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/无符号 long 类型转换为 2D/无符号 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 版本中更改: 当转换为字节视图时,不再限制源格式。
还有几个可用的只读属性
- 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 版本中更改: 现在根据 struct 模块语法处理格式
'B'
。这意味着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 风格的数组。该值仅供参考。
-
集合类型 — set
, frozenset
¶
集合对象是不同可哈希对象的无序集合。常见用途包括成员资格测试、从序列中删除重复项,以及计算数学运算,例如交集、并集、差集和对称差集。(有关其他容器,请参阅内置的 dict
、 list
和 tuple
类,以及 collections
模块。)
与其他集合一样,集合支持 x in set
、len(set)
和 for x in set
。作为无序集合,集合不记录元素位置或插入顺序。因此,集合不支持索引、切片或其他类似序列的行为。
目前有两种内置的集合类型,set
和 frozenset
。set
类型是可变的 — 可以使用诸如 add()
和 remove()
之类的方法更改内容。由于它是可变的,因此它没有哈希值,不能用作字典键或另一个集合的元素。frozenset
类型是不可变的且可哈希的 — 其内容在创建后无法更改;因此,它可以作为字典键或另一个集合的元素使用。
非空集合(不是 frozenset)可以通过将用逗号分隔的元素列表放在大括号内来创建,例如:{'jack', 'sjoerd'}
,除了 set
构造函数之外。
两个类的构造函数的工作方式相同
- class set([iterable])¶
- class frozenset([iterable])¶
返回一个新集合或 frozenset 对象,其元素取自 iterable。集合的元素必须是 可哈希的。要表示集合的集合,内部集合必须是
frozenset
对象。如果未指定 iterable,则返回一个新的空集合。可以通过多种方式创建集合
使用大括号内用逗号分隔的元素列表:
{'jack', 'sjoerd'}
使用集合推导式:
{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。
映射类型 — dict
¶
映射 对象将 可哈希 值映射到任意对象。映射是可变对象。目前只有一个标准的映射类型,即字典。(有关其他容器,请参阅内置的 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'}
使用字典推导式:
{}
,{x: x ** 2 for x in range(10)}
使用类型构造函数:
dict()
、dict([('foo', 100), ('bar', 200)])
、dict(foo=100, bar=200)
如果没有提供位置参数,则创建一个空字典。如果提供了位置参数,并且它定义了一个
keys()
方法,则通过使用该方法返回的每个键在参数上调用__getitem__()
来创建字典。否则,位置参数必须是一个可迭代对象。可迭代中的每个项目本身必须是一个恰好包含两个元素的可迭代对象。每个项目的第一个元素成为新字典中的一个键,第二个元素成为对应的值。如果一个键出现多次,则该键的最后一个值将成为新字典中的对应值。如果提供了关键字参数,则将关键字参数及其值添加到从位置参数创建的字典中。如果要添加的键已存在,则关键字参数的值将替换位置参数的值。
为了说明这一点,以下示例都返回一个等于
{"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 标识符的键。否则,可以使用任何有效键。
这些是字典支持的操作(因此,自定义映射类型也应该支持)
- 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
的部分实现。collections.defaultdict
使用不同的__missing__
方法。
- 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* 来说,成为一个可变对象(如空列表)通常没有意义。要获取不同的值,请改用 字典推导式 。
- get(key, default=None)¶
如果 *key* 在字典中,则返回 *key* 的值,否则返回 *default*。 如果未给定 *default*,则默认为
None
,因此此方法永远不会引发KeyError
。
- 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([other])¶
使用来自 *other* 的键/值对更新字典,覆盖现有键。返回
None
。update()
接受具有keys()
方法的另一个对象(在这种情况下,将使用该方法返回的每个键调用__getitem__()
)或者键/值对的可迭代对象(作为元组或其他长度为 2 的可迭代对象)。如果指定了关键字参数,则字典将使用这些键/值对进行更新: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* 可以是 映射 或键/值对的可迭代对象。当 *d* 和 *other* 共享键时,*other* 的值具有更高的优先级。
3.9 版本新增。
当且仅当字典具有相同的
(key, value)
对(与顺序无关)时,它们才相等。顺序比较('<'、'<='、'>='、'>')引发TypeError
异常。字典保留插入顺序。请注意,更新键不会影响顺序。删除后添加的键将插入到末尾。
>>> 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 版本中更改: 字典顺序保证为插入顺序。此行为是 3.6 版本 CPython 的一个实现细节。
字典和字典视图是可逆的。
>>> 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* 在基础字典的键、值或条目中,则返回
True
(在后一种情况下,*x* 应为(key, value)
元组)。
- reversed(dictview)
返回字典的键、值或条目的反向迭代器。视图将按照插入的相反顺序迭代。
在 3.8 版本中更改: 字典视图现在是可逆的。
- dictview.mapping
返回一个
types.MappingProxyType
,它封装了视图所引用的原始字典。在 3.10 版本中新增。
键视图是类集合的,因为它们的条目是唯一的且是可哈希的。项目视图也具有类集合的操作,因为(键,值)对是唯一的且键是可哈希的。如果项目视图中的所有值也都是可哈希的,则项目视图可以与其他集合互操作。(值视图不被视为类集合的,因为条目通常不是唯一的。)对于类集合的视图,为抽象基类 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
上下文管理器类型¶
Python 的 with
语句支持由上下文管理器定义的运行时上下文的概念。这是通过一对方法实现的,这些方法允许用户定义的类定义一个运行时上下文,该上下文在语句体执行之前进入,并在语句结束时退出。
- contextmanager.__enter__()¶
进入运行时上下文,并返回此对象或与运行时上下文相关的另一个对象。此方法返回的值绑定到使用此上下文管理器的
with
语句的as
子句中的标识符。一个返回自身的上下文管理器的例子是 文件对象。文件对象从 __enter__() 返回自身,以允许在
with
语句中将open()
用作上下文表达式。一个返回相关对象的上下文管理器的例子是由
decimal.localcontext()
返回的上下文管理器。这些管理器将活动的小数上下文设置为原始小数上下文的副本,然后返回该副本。这允许在with
语句的主体中更改当前的小数上下文,而不会影响with
语句之外的代码。
- contextmanager.__exit__(exc_type, exc_val, exc_tb)¶
退出运行时上下文,并返回一个布尔标志,指示是否应抑制发生的任何异常。如果在执行
with
语句的主体时发生异常,则参数包含异常类型、值和回溯信息。否则,所有三个参数都为None
。从此方法返回 true 值将导致
with
语句抑制异常,并继续执行紧跟在with
语句之后的语句。否则,异常会在此方法执行完成后继续传播。在此方法执行期间发生的异常将替换在with
语句主体中发生的任何异常。传入的异常绝不应显式地重新引发 - 相反,此方法应返回 false 值,以指示该方法已成功完成,并且不希望抑制引发的异常。这允许上下文管理代码轻松检测
__exit__()
方法是否真的失败。
Python 定义了几个上下文管理器,以支持轻松的线程同步、快速关闭文件或其他对象,以及更简单地操作活动的小数算术上下文。除了它们对上下文管理协议的实现之外,这些特定类型没有得到特殊处理。有关示例,请参阅 contextlib
模块。
Python 的 生成器 和 contextlib.contextmanager
装饰器提供了一种实现这些协议的便捷方法。如果使用 contextlib.contextmanager
装饰器修饰生成器函数,它将返回一个实现必要的 __enter__()
和 __exit__()
方法的上下文管理器,而不是未修饰的生成器函数产生的迭代器。
请注意,Python/C API 中 Python 对象的类型结构中没有这些方法的特定槽位。希望定义这些方法的扩展类型必须将它们作为普通的 Python 可访问方法提供。与设置运行时上下文的开销相比,单个类字典查找的开销可以忽略不计。
类型注解类型 — 泛型别名, 联合¶
泛型别名类型¶
GenericAlias
对象通常通过 下标 类来创建。它们最常与 容器类 一起使用,例如 list
或 dict
。例如,list[int]
是一个 GenericAlias
对象,它是通过使用参数 int
对 list
类进行下标而创建的。GenericAlias
对象主要用于 类型注解。
注意
通常只有当类实现了特殊方法 __class_getitem__()
时,才有可能对类进行下标。
GenericAlias
对象充当 泛型类型 的代理,实现参数化泛型。
对于容器类,提供给类的 下标 的参数可能指示对象包含的元素的类型。例如,set[bytes]
可以在类型注解中用于表示 set
,其中所有元素的类型都是 bytes
。
对于定义了 __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
,它是一种期望两个类型参数的泛型类型,分别表示键类型和值类型。在本例中,该函数期望一个dict
,其键类型为str
,值类型为int
。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(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]
可选类型可以拼写为与
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
联合对象的用户可见类型可以从 types.UnionType
访问,并用于 isinstance()
检查。不能从类型实例化对象。
>>> import types
>>> isinstance(int | str, types.UnionType)
True
>>> types.UnionType()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: cannot create 'types.UnionType' instances
注意
为支持语法 X | Y
,类型对象的 __or__()
方法被添加。如果元类实现了 __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 版本中新增。
其他内置类型¶
解释器支持几种其他类型的对象。其中大多数只支持一到两种操作。
模块¶
模块上唯一特殊的操作是属性访问: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'>
。
空对象¶
此对象由不显式返回值函数返回。它不支持任何特殊操作。只有一个空对象,名为 None
(一个内置名称)。type(None)()
生成相同的单例。
它被写成 None
。
省略号对象¶
此对象通常用于切片(请参阅 切片)。它不支持任何特殊操作。只有一个省略号对象,名为 Ellipsis
(一个内置名称)。type(Ellipsis)()
生成 Ellipsis
单例。
它写作 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)
.任何其他转换为基数 10 的字符串转换,例如
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
。
脚注