内置类型¶
以下部分描述了解释器中内置的标准类型。
主要内置类型是数字、序列、映射、类、实例和异常。
一些集合类是可变的。在原地添加、减去或重新排列其成员且不返回特定项的方法永远不会返回集合实例本身,而是返回 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
,但当发现 x < y
为假时,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 和 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 中添加。
浮点数上的附加方法¶
浮点数类型实现了 numbers.Real
抽象基类。浮点数还具有以下附加方法。
- 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'
数字类型的哈希¶
对于数字 x
和 y
,它们可能属于不同的类型,要求 hash(x) == hash(y)
,只要 x == y
(有关更多详细信息,请参阅 __hash__()
方法文档)。为了在各种数字类型(包括 int
、float
、decimal.Decimal
和 fractions.Fraction
)中实现和提高效率,Python 对数字类型的哈希基于一个针对任何有理数定义的单一数学函数,因此适用于 int
和 fractions.Fraction
的所有实例,以及 float
和 decimal.Decimal
的所有有限实例。从本质上讲,此函数由模 P
的约简给出,其中 P
是一个固定的质数。Python 可用 modulus
属性的形式获取 P
的值,该属性属于 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.14 中引发错误。
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__()
方法。有关生成器的更多信息,请参阅 生成器表达式文档。
序列类型 — list
、tuple
、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) |
|
s 从 i 到 j 的切片 |
(3)(4) |
|
s 从 i 到 j 的切片,步长为 k |
(3)(5) |
|
s 的长度 |
|
|
s 中最小的项目 |
|
|
s 中最大的项目 |
|
|
s 中 x 的第一次出现的索引(在索引 i 之后,索引 j 之前) |
(8) |
|
s 中 x 出现的总次数 |
相同类型的序列也支持比较。特别是,通过比较相应的元素,元组和列表按字典顺序进行比较。这意味着要进行相等比较,每个元素都必须进行相等比较,并且两个序列必须是同一种类型且具有相同的长度。(有关详细信息,请参阅语言参考中的 比较。)
可变序列上的正向和反向迭代器使用索引访问值。即使基础序列发生变异,该索引也将继续向前(或向后)移动。仅当遇到 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]]
可以在常见问题解答条目中找到进一步的解释 如何创建一个多维列表?。
如果 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,则切片为空。从 i 到 j 的 s 切片,步长为 k,被定义为具有索引
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)
。当 k 为负数时,如果 i 和 j 较大,则将它们减小到len(s) - 1
。如果省略 i 或 j 或None
,它们将变为“结束”值(哪个结束取决于 k 的符号)。请注意,k 不能为零。如果 k 为None
,则将其视为1
。连接不可变序列总是会生成一个新对象。这意味着通过重复连接来构建序列将在序列总长度中产生二次运行时成本。要获得线性运行时成本,您必须切换到以下备选方案之一
如果连接
str
对象,您可以构建一个列表并在最后使用str.join()
,或者将结果写入io.StringIO
实例,并在完成后检索其值如果连接
bytes
对象,您可以同样使用bytes.join()
或io.BytesIO
,或者您可以使用bytearray
对象进行就地连接。bytearray
对象是可变的,并且具有高效的超分配机制对于其他类型,请调查相关的类文档
某些序列类型(例如
range
)仅支持遵循特定模式的项目序列,因此不支持序列连接或重复。index
在 s 中找不到 x 时引发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
,因此默认情况下会移除并返回最后一个项目。remove()
在 s 中找不到 x 时引发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()
。列表实现所有 common 和 mutable 序列操作。列表还提供以下附加方法
- 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 元组作为唯一参数的函数调用。元组实现了所有 common 序列操作。
对于通过名称访问比通过索引访问更清晰的异构数据集合,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)) []
范围实现了所有 common 序列操作,除了连接和重复(因为范围对象只能表示遵循严格模式的序列,而重复和连接通常会违反该模式)。
- start¶
start 参数的值(或
0
,如果未提供参数)
- stop¶
stop 参数的值
- step¶
step 参数的值(或
1
,如果未提供参数)
与常规 list
或 tuple
相比,range
类型的优势在于,无论它表示的范围大小如何,range
对象始终占用相同(较小)的内存(因为它仅存储 start
、stop
和 step
值,根据需要计算各个项目和子范围)。
范围对象实现了 collections.abc.Sequence
ABC,并提供包含测试、元素索引查找、切片和对负索引的支持等功能(请参阅 序列类型 — 列表、元组、范围)
>>> 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 配方展示了如何实现适合浮点应用程序的范围延迟版本。
文本序列类型 — str
¶
Python 中的文本数据使用 str
对象或字符串处理。字符串是 Unicode 代码点的不可变 序列。字符串文字以多种方式编写
单引号:
'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(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
或bytearray
)。在这种情况下,如果 object 是bytes
(或bytearray
)对象,则str(bytes, encoding, errors)
等效于bytes.decode(encoding, errors)
。否则,在调用bytes.decode()
之前,将获取缓冲区对象底层的字节对象。有关缓冲区对象的信息,请参阅 二进制序列类型 — bytes、bytearray、memoryview 和 缓冲区协议。将
bytes
对象传递给str()
,而不使用 encoding 或 errors 参数,属于返回非正式字符串表示形式的第一种情况(另请参阅 Python 的-b
命令行选项)。例如>>> str(b'Zoot!') "b'Zoot!'"
有关
str
类及其方法的更多信息,请参阅 文本序列类型 — str 和下面的 字符串方法 部分。要输出格式化字符串,请参阅 f 字符串 和 格式字符串语法 部分。此外,请参阅 文本处理服务 部分。
字符串方法¶
字符串实现了所有 common 序列操作,以及下面描述的其他方法。
字符串还支持两种字符串格式化样式,一种提供高度的灵活性和自定义(请参阅 str.format()
、格式字符串语法 和 自定义字符串格式化),另一种基于 C printf
样式格式化,它处理的类型范围较窄,并且正确使用起来稍微困难一些,但对于它可以处理的情况通常更快(printf 样式字符串格式化)。
标准库的 文本处理服务 部分涵盖了许多其他模块,这些模块提供了各种与文本相关的实用程序(包括 re
模块中的正则表达式支持)。
- str.capitalize()¶
返回字符串的副本,其第一个字符大写,其余字符小写。
在 3.8 版中更改:第一个字符现在是大写,而不是小写。这意味着二合字母之类的字符只会将第一个字母大写,而不是整个字符。
- str.casefold()¶
返回字符串的折叠副本。折叠后的字符串可用于不区分大小写的匹配。
折叠类似于小写,但更激进,因为它旨在消除字符串中的所有大小写区别。例如,德语小写字母
'ß'
等同于"ss"
。由于它已经是小写,lower()
对'ß'
无效;casefold()
将其转换为"ss"
。折叠算法 在 Unicode 标准的 3.13 ‘Default Case Folding’ 部分中进行了描述。
在 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
),则会复制该字符并将当前列重置为零。任何其他字符都将保持不变地复制,并且无论字符在打印时如何表示,当前列都会增加一。>>> '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
和子类)时,该函数会暂时将LC_CTYPE
区域设置设为LC_NUMERIC
区域设置,以解码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
。如果以下条件之一返回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
。十进制字符是可用于在 10 进制中形成数字的字符,例如 U+0660,阿拉伯-印度数字零。形式上,十进制字符是 Unicode 通用类别“Nd”中的字符。
- str.isdigit()¶
如果字符串中的所有字符都是数字且至少有一个字符,则返回
True
,否则返回False
。数字包括十进制字符和需要特殊处理的数字,例如兼容上标数字。这涵盖了无法用于在 10 进制中形成数字的数字,例如 Kharosthi 数字。形式上,数字是一个具有属性值 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时分割字符串,并返回一个包含分隔符之前的部分、分隔符本身和分隔符之后的三个元组。如果找不到分隔符,则返回一个包含字符串本身以及两个空字符串的三元组。
- 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])¶
返回字符串的副本,其中所有子字符串old都替换为new。如果给出了可选参数count,则只替换前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 参数可以由多个字符组成(例如,'1<>2<>3'.split('<>')
返回['1', '2', '3']
)。使用指定的分隔符分割空字符串会返回['']
。例如
>>> '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
,则应用不同的分割算法:连续的空白字符被视为单个分隔符,并且如果字符串有前导或尾随空白字符,结果将不会包含任何空字符串。因此,使用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 且为真,否则结果列表中不包括换行符。
此方法在以下行边界处分割。特别是,这些边界是 通用换行符 的超集。
表示
说明
\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']
与
split()
不同,当给定分隔符字符串 sep 时,此方法会为一个空字符串返回一个空列表,并且终端换行符不会导致额外的行>>> "".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()
。
如果 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'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)
从整数的 iterable 中:
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 参数,以便在十六进制输出中的字节之间插入分隔符。
由于字节对象是整数序列(类似于元组),对于字节对象 b,b[0]
将是一个整数,而 b[0:1]
将是一个长度为 1 的字节对象。(这与文本字符串形成对比,其中索引和切片都会产生长度为 1 的字符串)
字节对象的表示形式使用文本格式 (b'...'
),因为它通常比例如 bytes([46, 46, 46])
更有用。你始终可以使用 list(b)
将字节对象转换成整数列表。
字节数组对象¶
- class bytearray([source[, encoding[, errors]]])¶
没有针对字节数组对象的专用文本语法,而是始终通过调用构造函数来创建它们
创建空实例:
bytearray()
使用给定长度创建零填充实例:
bytearray(10)
从整数的可迭代对象:
bytearray(range(20))
通过缓冲区协议复制现有二进制数据:
bytearray(b'Hi!')
由于 bytearray 对象是可变的,因此除了 字节和 bytearray 操作 中描述的常见字节和 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 对象的表示形式使用字节文本格式 (bytearray(b'...')
),因为它通常比例如 bytearray([46, 46, 46])
更有用。您可以始终使用 list(b)
将 bytearray 对象转换为整数列表。
字节和 bytearray 操作¶
字节和字节数组对象都支持通用序列操作。它们不仅与同类型的操作数交互,还与任何类字节对象交互。由于这种灵活性,它们可以在操作中自由混合,而不会导致错误。但是,结果的返回类型可能取决于操作数的顺序。
注意
字节和字节数组对象上的方法不接受字符串作为其参数,就像字符串上的方法不接受字节作为其参数一样。例如,您必须编写
a = "abc"
b = a.replace("a", "f")
和
a = b"abc"
b = a.replace(b"a", b"f")
一些字节和字节数组操作假定使用兼容 ASCII 的二进制格式,因此在处理任意二进制数据时应避免使用这些操作。以下介绍了这些限制。
注意
使用这些基于 ASCII 的操作来处理未存储为基于 ASCII 的格式的二进制数据可能会导致数据损坏。
字节和字节数组对象上的以下方法可用于任意二进制数据。
- 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可以是任何类字节对象。
注意
此方法的字节数组版本不就地操作 - 即使未进行任何更改,它始终会生成一个新对象。
在 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可以是任何类字节对象。
注意
此方法的字节数组版本不就地操作 - 即使未进行任何更改,它始终会生成一个新对象。
在 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 版中更改:现在在Python 开发模式和调试模式中检查errors参数的值。
- 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)¶
返回一个字节或字节数组对象,它是 iterable 中二进制数据序列的连接。如果 iterable 中有任何值不是 类字节对象(包括
str
对象),则会引发TypeError
。元素之间的分隔符是提供此方法的字节或字节数组对象的内容。
- 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 元组。如果未找到分隔符,则返回一个包含原始序列副本的 3 元组,后跟两个空字节或 bytearray 对象。
要搜索的分隔符可以是任何 类似字节的对象。
- bytes.replace(old, new[, count])¶
- bytearray.replace(old, new[, count])¶
返回序列的副本,其中所有子序列old的出现都替换为new。如果给出了可选参数count,则只替换前count个出现。
要搜索的子序列及其替换可以是任何 类似字节的对象。
注意
此方法的字节数组版本不就地操作 - 即使未进行任何更改,它始终会生成一个新对象。
- 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 元组。如果未找到分隔符,则返回一个包含两个空字节或 bytearray 对象的 3 元组,后跟原始序列的拷贝。
要搜索的分隔符可以是任何 类似字节的对象。
- bytes.startswith(prefix[, start[, end]])¶
- bytearray.startswith(prefix[, start[, end]])¶
如果二进制数据以指定的前缀开头,则返回
True
,否则返回False
。前缀也可以是前缀元组。使用可选的开始,从该位置开始测试。使用可选的结束,在该位置停止比较。要搜索的前缀可以是任何 类似字节的对象。
- bytes.translate(table, /, delete=b'')¶
- bytearray.translate(table, /, delete=b'')¶
返回字节或字节数组对象的副本,其中删除可选参数delete中出现的所有字节,并且剩余字节已通过给定的转换表进行映射,该转换表必须是长度为 256 的字节对象。
可以使用
bytes.maketrans()
方法创建转换表。对于仅删除字符的转换,将table 参数设置为
None
>>> b'read this short text'.translate(None, b'aeiou') b'rd ths shrt txt'
3.6 版中已更改: 现在支持将delete 作为关键字参数。
字节和字节数组对象上的以下方法具有默认行为,该行为假定使用 ASCII 兼容二进制格式,但仍可以通过传递适当的参数来与任意二进制数据一起使用。请注意,本节中的所有字节数组方法不会就地操作,而是生成新对象。
- bytes.center(width[, fillbyte])¶
- bytearray.center(width[, fillbyte])¶
返回一个对象副本,该对象居中于长度为宽度的序列中。使用指定的填充字节进行填充(默认情况下为 ASCII 空格)。对于
bytes
对象,如果宽度小于或等于len(s)
,则返回原始序列。注意
此方法的字节数组版本不就地操作 - 即使未进行任何更改,它始终会生成一个新对象。
- bytes.ljust(width[, fillbyte])¶
- bytearray.ljust(width[, fillbyte])¶
返回一个对象副本,该对象左对齐于长度为宽度的序列中。使用指定的填充字节进行填充(默认情况下为 ASCII 空格)。对于
bytes
对象,如果宽度小于或等于len(s)
,则返回原始序列。注意
此方法的字节数组版本不就地操作 - 即使未进行任何更改,它始终会生成一个新对象。
- 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'
要删除的字节值的二进制序列可以是任何 类似字节的对象。请参阅
removeprefix()
,了解一种将删除单个前缀字符串而不是一组字符的方法。例如>>> b'Arthur: three!'.lstrip(b'Arthur: ') b'ee!' >>> b'Arthur: three!'.removeprefix(b'Arthur: ') b'three!'
注意
此方法的字节数组版本不就地操作 - 即使未进行任何更改,它始终会生成一个新对象。
- bytes.rjust(width[, fillbyte])¶
- bytearray.rjust(width[, fillbyte])¶
返回长度为width序列中右对齐的对象副本。使用指定的fillbyte(默认是 ASCII 空格)填充。对于
bytes
对象,如果width小于或等于len(s)
,则返回原始序列。注意
此方法的字节数组版本不就地操作 - 即使未进行任何更改,它始终会生成一个新对象。
- 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'
注意
此方法的字节数组版本不就地操作 - 即使未进行任何更改,它始终会生成一个新对象。
- bytes.split(sep=None, maxsplit=-1)¶
- bytearray.split(sep=None, maxsplit=-1)¶
使用二进制序列作为分隔符字符串,将二进制序列拆分为相同类型的子序列。如果给定且非负的maxsplit,则最多执行maxsplit拆分(因此,列表最多有
maxsplit+1
元素)。如果未指定maxsplit或为-1
,则拆分次数没有限制(执行所有可能的拆分)。如果给定sep,则连续分隔符不会组合在一起,并且被视为分隔空子序列(例如,
b'1,,2'.split(b',')
返回[b'1', b'', b'2']
)。sep参数可以包含多字节序列(例如,b'1<>2<>3'.split(b'<>')
返回[b'1', b'2', b'3']
)。使用指定的分隔符拆分空序列将返回[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'']
如果未指定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 对象上的以下方法假定使用与 ASCII 兼容的二进制格式,不应将其应用于任意二进制数据。请注意,本节中的所有 bytearray 方法不会就地操作,而是生成新对象。
- bytes.capitalize()¶
- bytearray.capitalize()¶
返回一个序列的副本,其中每个字节都被解释为 ASCII 字符,第一个字节大写,其余字节小写。非 ASCII 字节值将保持不变。
注意
此方法的字节数组版本不就地操作 - 即使未进行任何更改,它始终会生成一个新对象。
- 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'
注意
此方法的字节数组版本不就地操作 - 即使未进行任何更改,它始终会生成一个新对象。
- 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 大写字母字符都转换为相应的 ASCII 小写字母字符。
例如
>>> b'Hello World'.lower() b'hello world'
小写 ASCII 字符是序列
b'abcdefghijklmnopqrstuvwxyz'
中的那些字节值。大写 ASCII 字符是序列b'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
中的那些字节值。注意
此方法的字节数组版本不就地操作 - 即使未进行任何更改,它始终会生成一个新对象。
- 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']
与
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
。即使对于任意 Unicode 代码点通常并非如此,大小写转换在 ASCII 中也是对称的。注意
此方法的字节数组版本不就地操作 - 即使未进行任何更改,它始终会生成一个新对象。
- 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."
注意
此方法的字节数组版本不就地操作 - 即使未进行任何更改,它始终会生成一个新对象。
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。
注意
此方法的字节数组版本不就地操作 - 即使未进行任何更改,它始终会生成一个新对象。
另请参阅
PEP 461 - 向字节和字节数组添加 % 格式化
在 3.5 版中添加。
内存视图¶
memoryview
对象允许 Python 代码访问支持 缓冲区协议 的对象的内部数据,而无需复制。
- class memoryview(object)¶
创建一个引用对象
memoryview
。对象必须支持缓冲区协议。支持缓冲区协议的内置对象包括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
模块中的本机格式说明符之一,则还支持使用整数或整数元组进行索引,并返回具有正确类型的单个元素。一维内存视图可以用整数或一个整数元组进行索引。多维内存视图可以用恰好为 ndim 个整数的元组进行索引,其中 ndim 是维数。零维内存视图可以用空元组进行索引。下面是一个非字节格式的示例
>>> import array >>> a = array.array('l', [-11111111, 22222222, -33333333, 44444444]) >>> m = memoryview(a) >>> m[0] -11111111 >>> m[-1] 44444444 >>> m[::2].tolist() [-11111111, -33333333]
如果基础对象可写,则内存视图支持一维切片赋值。不允许调整大小
>>> 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”的一维内存视图(只读)类型也是可哈希的。哈希定义为
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 中更改:一维内存视图现在可以切片。具有格式“B”、“b”或“c”的一维内存视图现在是 可哈希的。
在版本 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
请注意,与浮点数一样,
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([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,但缓冲区本身不会被复制。支持的转换是一维 -> C-contiguous 和 C-contiguous -> 一维。目标格式被限制为
struct
语法中的单个元素本机格式。其中一种格式必须是字节格式(“B”、“b”或“c”)。结果的字节长度必须与原始长度相同。请注意,所有字节长度都可能取决于操作系统。将一维/长转换为一维/无符号字节
>>> 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
将一维/无符号字节转换为一维/字符
>>> 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')
将一维/字节转换为三维/整数转换为一维/有符号字符
>>> 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
将一维/无符号长转换为二维/无符号长
>>> 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 中更改: format
'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 样式的数组。该值仅供参考。
集合类型 — set
、frozenset
¶
set 对象是不同可哈希对象的无序集合。常见用法包括成员资格测试、从序列中删除重复项以及计算数学运算,如交集、并集、差集和对称差集。(对于其他容器,请参阅内置dict
、list
和tuple
类以及collections
模块。)
与其他集合类似,集合支持x in set
、len(set)
和for x in set
。作为无序集合,集合不记录元素位置或插入顺序。因此,集合不支持索引、切片或其他类似序列的行为。
目前有两种内置集合类型,set
和frozenset
。set
类型是可变的——可以使用add()
和remove()
等方法更改内容。由于它是可变的,因此它没有哈希值,不能用作字典键或另一个集合的元素。frozenset
类型是不可变的且可哈希的——创建后其内容无法更改;因此,它可以用作字典键或另一个集合的元素。
可以通过在大括号内放置元素的逗号分隔列表来创建非空集合(不是冻结集合),例如:{'jack', 'sjoerd'}
,除了set
构造函数。
这两个类的构造函数工作方式相同
- class set([iterable])¶
- class frozenset([iterable])¶
返回一个新的集合或冻结集合对象,其元素取自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)
如果没有给出位置参数,则创建一个空字典。如果给出了位置参数并且它是一个映射对象,则创建一个具有与映射对象相同的键值对的字典。否则,位置参数必须是可迭代对象。可迭代对象中的每个项目本身都必须是具有正好两个对象的可迭代对象。每个项目的第一个对象成为新字典中的键,第二个对象成为相应的键值。如果键出现多次,则该键的最后一个值将成为新字典中的相应值。
如果给出了关键字参数,则将关键字参数及其值添加到从位置参数创建的字典中。如果要添加的键已存在,则关键字参数中的值将替换位置参数中的值。
为了说明,以下示例都返回一个等于
{"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]
返回键为 key 的 d 的项。如果 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()¶
返回字典的浅拷贝。
- 类方法 fromkeys(iterable, value=None, /)¶
使用来自iterable的键和设置为value的值创建一个新字典。
fromkeys()
是一个返回新字典的类方法。value默认为None
。所有值都仅引用单个实例,因此通常没有意义让value成为可变对象,例如空列表。要获取不同的值,请改用字典解析。
- popitem()¶
从字典中删除并返回一个
(key, value)
对。对以LIFO顺序返回。popitem()
可用于破坏性地迭代字典,这通常用于集合算法。如果字典为空,则调用popitem()
会引发KeyError
。3.7 版中已更改:现在保证 LIFO 顺序。在以前的版本中,
popitem()
将返回任意键/值对。
- reversed(d)
返回字典键的反向迭代器。这是
reversed(d.keys())
的快捷方式。在版本 3.8 中添加。
- setdefault(key, default=None)¶
如果字典中存在 key,则返回其值。如果不存在,则使用 default 的值插入 key,并返回 default。default 的默认值为
None
。
- update([other])¶
使用 other 中的键/值对更新字典,覆盖现有键。返回
None
。update()
接受另一个字典对象或键/值对的迭代对象(作为元组或其他长度为 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 在底层字典的键、值或项中(在后一种情况下,x 应为
(key, value)
元组),则返回True
。
- 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]
是通过使用参数 int
对 list
类进行下标而创建的 GenericAlias
对象。 GenericAlias
对象主要用于 类型注释。
注意
通常,只有在类实现了特殊方法 __class_getitem__()
时,才有可能对类进行下标。
GenericAlias
对象充当 泛型类型 的代理,实现参数化泛型。
对于容器类,提供给类 订阅 的参数可能指示对象包含的元素类型。例如,set[bytes]
可用于类型注释中,表示 set
,其中所有元素的类型为 bytes
。
对于定义 __class_getitem__()
但不是容器的类,提供给类订阅的参数通常会指示对象上定义的一个或多个方法的返回类型。例如,regular expressions
可用于 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
,表示类型T
,该类型由类型 X、Y 等参数化,具体取决于所使用的T
。例如,一个函数期望list
包含float
元素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(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__¶
此属性是泛型类原始
__class_getitem__()
传递的泛型类型的tuple
(可能长度为 1)>>> 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__¶
如果别名已使用
*
运算符解包,则为 true(请参见TypeVarTuple
)。在版本 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
注意
添加 __or__()
方法用于类型对象,以支持语法 X | Y
。如果元类实现了 __or__()
,则联合可能会覆盖它
>>> 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
语法和联合类型的 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__
会引发 审计事件 object.__getattr__
,其参数为 obj
和 "__code__"
。
可以通过将代码对象(而不是源字符串)传递给 exec()
或 eval()
内置函数来执行或计算代码对象。
有关更多信息,请参阅 标准类型层次结构。
类型对象¶
类型对象表示各种对象类型。可以通过内置函数 type()
访问对象的类型。对类型没有特殊操作。标准模块 types
为所有标准内置类型定义了名称。
类型以这种方式编写: <class 'int'>
。
空对象¶
此对象由不显式返回值的函数返回。它不支持任何特殊操作。只有一个空对象,名为 None
(一个内置名称)。type(None)()
产生相同的单例。
它被写为 None
。
省略号对象¶
此对象通常用于切片(请参阅 切片)。它不支持任何特殊操作。只有一个省略号对象,名为 Ellipsis
(一个内置名称)。type(Ellipsis)()
产生 Ellipsis
单例。
它被写为 Ellipsis
或 ...
。
未实现对象¶
当比较和二进制运算被要求对它们不支持的类型进行操作时,会返回此对象。有关更多信息,请参阅 比较。只有一个 NotImplemented
对象。 type(NotImplemented)()
产生单例实例。
它被写为 NotImplemented
。
内部对象¶
特殊属性¶
实现向几个对象类型添加了一些特殊只读属性,这些属性在相关时添加。其中一些不会由dir()
内置函数报告。
- object.__dict__¶
用于存储对象(可写)属性的字典或其他映射对象。
- instance.__class__¶
类实例所属的类。
- class.__bases__¶
类对象的基类的元组。
- definition.__name__¶
类、函数、方法、描述符或生成器实例的名称。
- class.__mro__¶
此属性是在方法解析期间查找基类时考虑的类的元组。
- class.__subclasses__()¶
每个类都保留对其直接子类的弱引用列表。此方法返回所有仍存活的引用的列表。该列表按定义顺序排列。示例
>>> int.__subclasses__() [<class 'bool'>, <enum 'IntEnum'>, <flag 'IntFlag'>, <class 're._constants._NamedIntConstant'>]
整数字符串转换长度限制¶
CPython 对在 int
和 str
之间进行转换设置了一个全局限制,以减轻拒绝服务攻击。此限制仅适用于十进制或其他非 2 的幂次方数基。十六进制、八进制和二进制转换不受限制。可以配置限制。
CPython 中的 int
类型是一个以二进制形式存储的任意长度数字(通常称为“大整数”)。不存在一种算法可以在线性时间内将字符串转换为二进制整数或将二进制整数转换为字符串,除非基数是 2 的幂次方。即使是已知的最佳 10 进制算法也具有次二次复杂度。转换诸如 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
中所提供。可以在 sys.int_info.str_digits_check_threshold
中提供的 640 位数字中配置最低限制。
验证
>>> 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
。
脚注