内置类型 — Python 文档

来自菜鸟教程
Python/docs/3.10/library/stdtypes
跳转至:导航、​搜索

内置类型

以下部分描述了内置于解释器中的标准类型。

主要的内置类型是数字、序列、映射、类、实例和异常。

一些集合类是可变的。 添加、减去或重新排列其成员的方法,并且不返回特定项,从不返回集合实例本身,而是返回 None

某些操作由多种对象类型支持; 特别是,几乎所有对象都可以比较相等性、测试真值并转换为字符串(使用 repr() 函数或稍微不同的 str() 函数) . 当对象由 print() 函数写入时,后一个函数被隐式使用。

真值测试

可以测试任何对象的真值,用于 ifwhile 条件或作为以下布尔运算的操作数。

默认情况下,一个对象被认为是真的,除非它的类定义了一个返回 False__bool__() 方法或一个返回零的 __len__() 方法,当与对象一起调用时。 1 以下是大多数被认为是假的内置对象:


  • 定义为 false 的常量:NoneFalse
  • 任何数字类型的零:00.00jDecimal(0)Fraction(0, 1)
  • 空序列和集合:()[]{}set()range(0)

除非另有说明,否则具有布尔结果的运算和内置函数始终返回 0False 为假,1True 为真。 (重要的例外:布尔运算 orand 总是返回它们的操作数之一。)


布尔运算 — and、or、not

这些是布尔运算,按优先级升序排列:

手术 结果 笔记
x or y 如果 x 为假,则为 y,否则为 x (1)
x and y 如果 x 为假,则为 x,否则为 y (2)
not x 如果 x 为假,则为 True,否则为 False (3)

笔记:

  1. 这是一个短路运算符,因此它仅在第一个参数为假时才计算第二个参数。
  2. 这是一个短路运算符,因此它仅在第一个参数为真时才计算第二个参数。
  3. not 的优先级低于非布尔运算符,因此 not a == b 被解释为 not (a == b),而 a == not b 是语法错误。


比较

Python 中有八种比较操作。 它们都具有相同的优先级(高于布尔运算的优先级)。 比较可以任意链接; 例如,x < y <= z 等价于 x < y and y <= z,除了 y 只计算一次(但在这两种情况下 z x < y被发现是假的)。

下表总结了比较操作:

手术 意义
< 严格小于
<= 小于或等于
> 严格大于
>= 大于或等于
== 平等的
!= 不相等
is 对象身份
is not 否定对象身份

不同类型的对象,除了不同的数字类型,永远不会比较相等。 == 运算符总是被定义,但对于某些对象类型(例如,类对象)相当于 is<<=>>= 运算符仅在有意义的地方定义; 例如,当其中一个参数是复数时,它们会引发 TypeError 异常。

除非类定义了 __eq__() 方法,否则类的不相同实例通常比较为不相等。

类的实例不能相对于同一类的其他实例或其他类型的对象进行排序,除非该类定义了足够多的方法 __lt__()__le__()__gt__() ] 和 __ge__()(通常,__lt__()__eq__() 就足够了,如果您想要比较运算符的常规含义)。

isis not 运算符的行为无法自定义; 它们也可以应用于任何两个对象并且永远不会引发异常。

另外两个具有相同语法优先级的操作,innot in,由 iterable 类型或实现 __contains__() 方法支持。


数字类型 — int、float、complex

共有三种不同的数字类型:整数浮点数复数。 此外,布尔值是整数的子类型。 整数具有无限的精度。 浮点数在C中通常使用double来实现; sys.float_info 中提供了有关运行程序的机器的浮点数的精度和内部表示的信息。 复数有实部和虚部,每个都是浮点数。 要从复数 z 中提取这些部分,请使用 z.realz.imag。 (标准库包括额外的数字类型 fractions.Fraction,用于有理数,以及 decimal.Decimal,用于具有用户可定义精度的浮点数。)

数字由数字文字或作为内置函数和运算符的结果创建。 未经修饰的整数文字(包括十六进制、八进制和二进制数)产生整数。 包含小数点或指数符号的数字文字产生浮点数。 将 'j''J' 附加到数字字面量会产生一个虚数(实部为零的复数),您可以将其添加到整数或浮点数上以获得具有实部和虚部的复数部分。

Python 完全支持混合算术:当二元算术运算符具有不同数字类型的操作数时,具有“较窄”类型的操作数会被扩展为另一个类型的操作数,其中整数比浮点数窄,浮点数比复数窄。 不同类型的数字之间的比较表现得好像正在比较这些数字的确切值。 2

构造函数 int()float()complex() 可用于生成特定类型的数字。

所有数值类型(复数除外)都支持以下运算(运算优先级见运算符优先级):

手术 结果 笔记 完整的文档
x + y xy 之和
x - y xy 的区别
x * y xy 的乘积
x / y xy 的商
x // y xy 的底商 (1)
x % y x / y 的余数 (2)
-x x 否定
+x x 不变
abs(x) x 的绝对值或大小 abs()
int(x) x 转换为整数 (3)(6) int()
float(x) x 转换为浮点数 (4)(6) float()
complex(re, im) 一个复数,实部 re,虚部 imim 默认为零。 (6) complex()
c.conjugate() 复数 c 的共轭
divmod(x, y) (x // y, x % y) (2) divmod()
pow(x, y) xy 的幂 (5) pow()
x ** y xy 的幂 (5)

笔记:

  1. 也称为整数除法。 结果值是一个整数,尽管结果的类型不一定是 int。 结果总是向负无穷大舍入:1//20(-1)//2-11//(-2)-1 , (-1)//(-2)0

  2. 不适用于复数。 如果合适,而是使用 abs() 转换为浮点数。

  3. 从浮点数到整数的转换可以像在 C 中一样舍入或截断; 请参阅函数 math.floor()math.ceil() 以获得明确定义的转换。

  4. float 还接受带有可选前缀“+”或“-”的字符串“nan”和“inf”,表示非数字 (NaN) 和正无穷大或负无穷大。

  5. Python 将 pow(0, 0)0 ** 0 定义为 1,这在编程语言中很常见。

  6. 接受的数字文字包括数字 09 或任何 Unicode 等价物(具有 Nd 属性的代码点)。

    请参阅 https://www.unicode.org/Public/13.0.0/ucd/extracted/DerivedNumericType.txt 以获取具有 Nd 属性的完整代码点列表。

所有 numbers.Real 类型(intfloat)还包括以下操作:

手术 结果
math.trunc(x) x 截断为 Integral
round(x[, n]) x 四舍五入为 n 位,四舍五入到偶数。 如果省略 n,则默认为 0。
math.floor(x) 最伟大的不可缺少的 <= X
math.ceil(x) 最小 积分 >= x

有关其他数字运算,请参阅 mathcmath 模块。

整数类型的按位运算

按位运算只对整数有意义。 按位运算的结果的计算就像在具有无限数量符号位的二进制补码中执行一样。

二元按位运算的优先级均低于数值运算,高于比较; 一元运算 ~ 与其他一元数值运算(+-)具有相同的优先级。

下表列出了按优先级升序排列的按位运算:

手术 结果 笔记
y xy 的按位 (4)
x ^ y xy 的按位 异或 (4)
x & y xy 的按位 (4)
x << n x 左移 n (1)(2)
x >> n x 右移 n (1)(3)
~x x 的位反转

笔记:

  1. 负移位计数是非法的,会导致 ValueError 升高。
  2. 左移 n 位相当于乘以 pow(2, n)
  3. 右移 n 位相当于按 pow(2, n) 进行地板除法。
  4. 使用有限二进制补码表示中的至少一个额外符号扩展位(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, byteorder, *, 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 字节表示。 如果整数无法用给定的字节数表示,则会引发 OverflowError

byteorder 参数确定用于表示整数的字节顺序。 如果 byteorder"big",则最高有效字节位于字节数组的开头。 如果 byteorder"little",则最高有效字节位于字节数组的末尾。 要请求主机系统的本机字节顺序,请使用 sys.byteorder 作为字节顺序值。

signed 参数确定是否使用二进制补码来表示整数。 如果 signedFalse 并且给出了一个负整数,则会引发 OverflowErrorsigned 的默认值为 False

3.2 版中的新功能。

classmethod int.from_bytes(bytes, byteorder, *, 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 参数确定用于表示整数的字节顺序。 如果 byteorder"big",则最高有效字节位于字节数组的开头。 如果 byteorder"little",则最高有效字节位于字节数组的末尾。 要请求主机系统的本机字节顺序,请使用 sys.byteorder 作为字节顺序值。

signed 参数指示是否使用二进制补码来表示整数。

3.2 版中的新功能。

int.as_integer_ratio()

返回一对整数,其比率恰好等于原始整数且分母为正。 整数(整数)的整数比总是以整数为分子,1为分母。

3.8 版中的新功能。


浮动的附加方法

float 类型实现了 numbers.Real 抽象基类 。 float 还具有以下附加方法。

float.as_integer_ratio()
返回一对整数,其比率恰好等于原始浮点数且分母为正。 在无穷大上引发 OverflowError,在 NaN 上引发 ValueError
float.is_integer()

如果浮点实例有限且具有整数值,则返回 True,否则返回 False

>>> (-2.0).is_integer()
True
>>> (3.2).is_integer()
False

有两种方法支持与十六进制字符串的转换。 由于 Python 的浮点数在内部存储为二进制数,因此将浮点数转换为 decimal 字符串通常会涉及一个小的舍入误差。 相比之下,十六进制字符串允许精确表示和指定浮点数。 这在调试和数值工作时很有用。

float.hex()
以十六进制字符串形式返回浮点数的表示形式。 对于有限浮点数,此表示将始终包括前导 0x 和尾随 p 和指数。
classmethod float.fromhex(s)
返回由十六进制字符串 s 表示的浮点数的类方法。 字符串 s 可能有前导和尾随空格。

注意 float.hex() 是一个实例方法,而 float.fromhex() 是一个类方法。

十六进制字符串采用以下形式:

[sign] ['0x'] integer ['.' fraction] ['p' exponent]

其中可选的 sign 可以是 +-integerfraction 是十六进制数字字符串,[ X134X] 是带有可选前导符号的十进制整数。 大小写不重要,整数或分数中必须至少有一个十六进制数字。 此语法类似于 C99 标准第 6.4.4.2 节中指定的语法,也类似于 Java 1.5 中使用的语法。 特别是,float.hex() 的输出可用作 C 或 Java 代码中的十六进制浮点文字,以及由 C 的 %a 格式字符或 Java 的 Double.toHexStringfloat.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'

数字类型的散列

对于可能是不同类型的数字 xy,要求 hash(x) == hash(y) 每当 x == y(请参阅 __hash__() 方法文档)更多细节)。 为了简化各种数字类型的实现和效率(包括 intfloatdecimal.Decimalfractions.Fraction) Python 对数字类型的哈希基于为任何有理数定义的单个数学函数,因此适用于 intfractions.Fraction 的所有实例,以及 的所有有限实例X404X]float 和 decimal.Decimal。 本质上,这个函数是通过对固定质数 P 的归约模 P 给出的。 P 的值作为 sys.hash_infomodulus 属性提供给 Python。

以下是详细规则:

  • 如果 x = m / n 是非负有理数且 n 不能被 P 整除,则将 hash(x) 定义为 m * invmod(n, P) % P,其中 [ X132X] 给出 nP 的倒数。
  • 如果 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 用作正无穷大或负无穷大(分别)的哈希值。
  • 对于 复数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 代码示例,等效于内置哈希,用于计算有理数的哈希 floatcomplex

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

迭代器类型

Python 支持容器迭代的概念。 这是使用两种不同的方法实现的; 这些用于允许用户定义的类支持迭代。 下面更详细描述的序列始终支持迭代方法。

需要为容器对象定义一种方法来提供迭代支持:

container.__iter__()
返回一个迭代器对象。 该对象需要支持下面描述的迭代器协议。 如果容器支持不同类型的迭代,则可以提供额外的方法来专门为这些迭代类型请求迭代器。 (支持多种形式迭代的对象的一个例子是一个支持广度优先和深度优先遍历的树结构。)这个方法对应于 Python 对象的类型结构的 tp_iter 槽Python/C API。

迭代器对象本身需要支持以下两种方法,它们共同构成了迭代器协议

iterator.__iter__()
返回迭代器对象本身。 这是允许容器和迭代器与 forin 语句一起使用所必需的。 此方法对应于 Python/C API 中 Python 对象的类型结构的 tp_iter 槽。
iterator.__next__()
从容器中返回下一个项目。 如果没有其他项目,则引发 StopIteration 异常。 此方法对应于 Python/C API 中 Python 对象的类型结构的 tp_iternext 槽。

Python 定义了几个迭代器对象来支持对一般和特定序列类型、字典和其他更特殊形式的迭代。 除了迭代器协议的实现之外,特定类型并不重要。

一旦迭代器的 __next__() 方法引发 StopIteration,它必须在后续调用中继续这样做。 不遵守此属性的实现被视为已损坏。

发电机类型

Python 的 generators 提供了一种方便的方法来实现迭代器协议。 如果容器对象的 __iter__() 方法被实现为生成器,它将自动返回一个迭代器对象(技术上,一个生成器对象)提供 __iter__()__next__() 方法. 有关生成器的更多信息,请参见 产量表达式 的文档。


序列类型 — list、tuple、range

共有三种基本的序列类型:列表、元组和范围对象。 专门用于处理 二进制数据文本字符串 的其他序列类型在专用部分中进行了描述。

常见的序列操作

大多数序列类型都支持下表中的操作,包括可变的和不可变的。 提供 collections.abc.Sequence ABC 是为了更轻松地在自定义序列类型上正确实现这些操作。

此表列出了按优先级升序排列的序列操作。 表中st为同类型序列,nijk 是整数,而 x 是满足由 s 强加的任何类型和值限制的任意对象。

innot in 操作与比较操作具有相同的优先级。 +(连接)和*(重复)操作与相应的数字操作具有相同的优先级。 3

手术 结果 笔记
x in s True 如果 s 的一项等于 x,否则为 False (1)
x not in s False 如果 s 的一项等于 x,否则为 True (1)
s + t st 的串联 (6)(7)
s * nn * s 相当于将 s 添加到自身 n (2)(7)
s[i] is项,原点0 (3)
s[i:j] sij 的切片 (3)(4)
s[i:j:k] sij 的切片 k (3)(5)
len(s) s 的长度
min(s) s 的最小项
max(s) s 的最大项目
s.index(x[, i[, j]]) xs 中第一次出现的索引(在索引 i 处或之后和索引 j 之前) (8)
s.count(x) xs 中出现的总次数

相同类型的序列也支持比较。 特别是,元组和列表通过比较相应的元素按字典顺序进行比较。 这意味着要比较相等,每个元素必须比较相等,并且两个序列必须具有相同的类型和相同的长度。 (有关完整的详细信息,请参阅语言参考中的 Comparisons。)

笔记:

  1. 虽然 innot in 操作在一般情况下仅用于简单的包含测试,但一些特殊的序列(例如 strbytesbytearray) 也将它们用于子序列测试:

    >>> "gg" in "eggs"
    True
  2. n 小于 0 的值被视为 0(产生与 s 相同类型的空序列)。 请注意,序列 s 中的项目不会被复制; 它们被多次引用。 这常常困扰着新的 Python 程序员; 考虑:

    >>> lists = [[../]] * 3
    >>> lists
    [[], [], []]
    >>> lists[0].append(3)
    >>> lists
    [[3], [3], [3]]

    发生的事情是 Python/docs/3.10/library 是一个包含空列表的单元素列表,因此 Python/docs/3.10/library * 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条目如何创建多维列表?中提供了进一步的解释。

  3. 如果 ij 为负,则索引相对于序列的末尾 slen(s) + ilen(s) + j 为取代。 但请注意,-0 仍然是 0

  4. sij 的切片被定义为具有索引 k 的项目序列,使得 i <= k < j . 如果 ij 大于 len(s),则使用 len(s)。 如果省略 iNone,则使用 0。 如果省略 jNone,请使用 len(s)。 如果i大于或等于j,则切片为空。

  5. sij的片段k定义为索引为x = i + n*k的项目序列使得 0 <= n < (j-i)/k。 换句话说,索引是ii+ki+2*ki+3*k等等,当达到j时停止(但从不包括 j)。 当k为正时,ij如果更大则减少为len(s)。 当k为负数时,ij如果更大则减少为len(s) - 1。 如果省略 ijNone,它们将成为“结束”值(结束取决于 k 的符号)。 注意,k 不能为零。 如果 kNone,则将其视为 1

  6. 连接不可变序列总是会产生一个新对象。 这意味着通过重复串联构建序列将在总序列长度中产生二次运行成本。 要获得线性运行时成本,您必须切换到以下选项之一:

  7. 某些序列类型(例如 range)仅支持遵循特定模式的项目序列,因此不支持序列串联或重复。

  8. indexs 中未找到 x 时引发 ValueError。 并非所有实现都支持传递额外的参数 ij。 这些参数允许有效搜索序列的子部分。 传递额外的参数大致相当于使用 s[i:j].index(x),只是不复制任何数据,并且返回的索引相对于序列的开头而不是切片的开头。


不可变序列类型

不可变序列类型通常实现但可变序列类型没有实现的唯一操作是支持内置的 hash()

这种支持允许不可变序列,例如 tuple 实例,用作 dict 键并存储在 setfrozenset 实例中。

尝试对包含不可散列值的不可变序列进行散列将导致 TypeError


可变序列类型

下表中的操作是在可变序列类型上定义的。 提供了 collections.abc.MutableSequence ABC 以便更轻松地在自定义序列类型上正确实现这些操作。

在表中 s 是可变序列类型的实例,t 是任何可迭代对象,而 x 是满足任何类型和值限制的任意对象通过 s(例如,bytearray 只接受满足值限制 0 <= x <= 255 的整数)。

手术 结果 笔记
s[i] = x si替换为x
s[i:j] = t sij 的切片被可迭代 t 的内容替换
del s[i:j] s[i:j] = [] 相同
s[i:j:k] = t s[i:j:k] 的元素替换为 t 的元素 (1)
del s[i:j:k] 从列表中删除 s[i:j:k] 的元素
s.append(x) x 附加到序列的末尾(与 s[len(s):len(s)] = [x] 相同)
s.clear() s 中删除所有项目(与 del s[:] 相同) (5)
s.copy() 创建 s 的浅拷贝(与 s[:] 相同) (5)
s.extend(t)s += t t 的内容扩展 s(大部分与 s[len(s):len(s)] = t 相同)
s *= n 更新 s 其内容重复 n (6)
s.insert(i, x) i 给定的索引处将 x 插入 s(与 s[i:i] = [x] 相同)
s.pop()s.pop(i) 检索 i 处的项目,并将其从 s 中删除 (2)
s.remove(x) s 中删除第一项,其中 s[i] 等于 x (3)
s.reverse() s 的项目原地反转 (4)

笔记:

  1. t 必须与它正在替换的切片具有相同的长度。

  2. 可选参数 i 默认为 -1,因此默认情况下删除并返回最后一项。

  3. remove()s 中未找到 x 时引发 ValueError

  4. reverse() 方法在反转大序列时修改序列以节省空间。 为了提醒用户它是由副作用操作的,它不返回相反的顺序。

  5. 包含 clear()copy() 是为了与不支持切片操作的可变容器的接口(例如 dictset)保持一致。 copy() 不是 collections.abc.MutableSequence ABC 的一部分,但大多数具体的可变序列类都提供了它。

    3.3 版新增:clear()copy() 方法。

  6. 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()

列表实现了所有的 commonmutable 序列操作。 列表还提供以下附加方法:

sort(*, key=None, reverse=False)

此方法对列表进行原地排序,仅使用项目之间的 < 比较。 异常不会被抑制——如果任何比较操作失败,整个排序操作都将失败(并且列表可能会处于部分修改状态)。

sort() 接受两个只能通过关键字传递的参数(keyword-only arguments):

key 指定一个参数的函数,用于从每个列表元素中提取比较键(例如,key=str.lower)。 列表中每一项对应的key被计算一次,然后用于整个排序过程。 None 的默认值表示直接对列表项进行排序,无需计算单独的键值。

functools.cmp_to_key() 实用程序可用于将 2.x 样式的 cmp 函数转换为 key 函数。

reverse 是一个布尔值。 如果设置为 True,则列表元素的排序就像每次比较都颠倒了一样。

在对大序列进行排序时,此方法会在适当的位置修改序列以节省空间。 为了提醒用户它是通过副作用操作的,它不返回排序的序列(使用 sorted() 显式请求一个新的排序列表实例)。

sort() 方法保证稳定。 如果排序保证不改变比较相等的元素的相对顺序,则它是稳定的——这有助于多次排序(例如,按部门排序,然后按工资等级排序)。

有关排序示例和简短的排序教程,请参阅 Sorting HOW TO


元组

元组是不可变的序列,通常用于存储异构数据的集合(例如由 enumerate() 内置生成的 2 元组)。 元组还用于需要不可变的同构数据序列的情况(例如允许存储在 setdict 实例中)。

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])

范围构造函数的参数必须是整数(内置 int 或任何实现 __index__ 特殊方法的对象)。 如果省略 step 参数,则默认为 1。 如果省略 start 参数,则默认为 0。 如果 step 为零,则会引发 ValueError

对于正 步长 ,范围 r 的内容由公式 r[i] = start + step*i 确定,其中 i >= 0r[i] < stop

对于负的 step,范围的内容仍由公式 r[i] = start + step*i 确定,但约束为 i >= 0r[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

range 类型相对于常规 listtuple 的优势在于 range 对象将始终采用相同(小)数量内存,无论它代表的范围的大小(因为它只存储 startstopstep 值,根据需要计算单个项目和子范围)。

Range 对象实现了 collections.abc.Sequence ABC,并提供了诸如包含测试、元素索引查找、切片和对负索引的支持等功能(参见 Sequence Types — 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

测试范围对象与 ==!= 的相等性将它们作为序列进行比较。 也就是说,如果两个范围对象表示相同的值序列,则认为它们相等。 (请注意,比较相等的两个范围对象可能具有不同的 startstopstep 属性,例如 range(0) == range(2, 1, 3) 或 [ X158X]。)

3.2 版更改: 实现序列 ABC。 支持切片和负索引。 在恒定时间内测试 int 对象的成员资格,而不是遍历所有项目。


3.3 版更改: 定义 '==' 和 '!=' 以根据范围对象定义的值序列来比较范围对象(而不是根据对象身份进行比较)。


3.3 新功能: startstopstep 属性。


也可以看看

  • linspace recipe 展示了如何实现适用于浮点应用程序的范围的惰性版本。


文本序列类型 — str

Python 中的文本数据使用 str 对象或 strings 处理。 字符串是 Unicode 代码点的不可变 序列 。 字符串文字以多种方式编写:

  • 单引号:'allows embedded "double" quotes'
  • 双引号:"allows embedded 'single' quotes"
  • 三重引用:Three single quotes"""Three double quotes"""

三重引用的字符串可以跨越多行——所有相关的空格都将包含在字符串文字中。

作为单个表达式的一部分并且它们之间只有空格的字符串文字将被隐式转换为单个字符串文字。 即,("spam " "eggs") == "spam eggs"

请参阅 String and Bytes literals 以获取有关各种形式的字符串文字的更多信息,包括支持的转义序列,以及禁用大多数转义序列处理的 r(“原始”)前缀。

也可以使用 str 构造函数从其他对象创建字符串。

由于没有单独的“字符”类型,索引字符串会生成长度为 1 的字符串。 即,对于非空字符串 ss[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')

返回 objectstring 版本。 如果未提供 object,则返回空字符串。 否则,str() 的行为取决于是否给出了 encodingerrors,如下所示。

如果 encodingerrors 都没有给出,str(object) 返回 object.__str__(),这是“非正式的”或很好打印的字符串表示 对象 。 对于字符串对象,这是字符串本身。 如果 object 没有 __str__() 方法,则 str() 回退到返回 repr(object)

如果给出 encodingerrors 中的至少一个,则 object 应该是一个 bytes-like object(例如 bytesbytearray)。 在这种情况下,如果 object 是一个 bytes(或 bytearray)对象,那么 str(bytes, encoding, errors) 相当于 bytes.decode(编码,错误)。 否则,在调用 bytes.decode() 之前获取缓冲区对象下的字节对象。 有关缓冲区对象的信息,请参阅 二进制序列类型 — bytes、bytearray、memoryviewBuffer Protocol

在没有 encodingerrors 参数的情况下将 bytes 对象传递给 str() 属于返回非正式字符串表示的第一种情况(另请参阅 Python 的 -b 命令行选项)。 例如:

>>> str(b'Zoot!')
"b'Zoot!'"

有关 str 类及其方法的更多信息,请参阅下面的 文本序列类型 — str字符串方法 部分。 要输出格式化字符串,请参阅 格式化字符串文字格式化字符串语法 部分。 此外,请参阅 文本处理服务 部分。

字符串方法

字符串实现了所有的 common 序列操作,以及下面描述的其他方法。

字符串还支持两种字符串格式,一种提供了很大程度的灵活性和自定义(请参阅 str.format()Format String SyntaxCustom String Formatting ]) 和另一个基于 C printf 样式格式的格式,它处理的类型范围更窄,正确使用稍难,但对于它可以处理的情况通常更快(printf-style String Formatting )。

标准库的 文本处理服务 部分涵盖了许多其他模块,这些模块提供了各种与文本相关的实用程序(包括 re 模块中的正则表达式支持)。

str.capitalize()

返回字符串的副本,其中第一个字符大写,其余字符小写。

在 3.8 版更改: 第一个字符现在放入标题而不是大写。 这意味着像二合字母这样的字符只会将它们的第一个字母大写,而不是完整的字符。

str.casefold()

返回字符串的 casefolded 副本。 大小写折叠字符串可用于无大小写匹配。

Casefolding 类似于小写,但更具侵略性,因为它旨在消除字符串中的所有大小写区别。 例如,德语小写字母 'ß' 相当于 "ss"。 由于它已经是小写的,所以 lower()'ß' 没有任何作用; casefold() 将其转换为 "ss"

casefolding 算法在 Unicode 标准的第 3.13 节中描述。

3.3 版中的新功能。

str.center(width[, fillchar])
以长度为 宽度 的字符串为中心返回。 填充是使用指定的 fillchar(默认为 ASCII 空间)完成的。 如果 width 小于或等于 len(s),则返回原始字符串。
str.count(sub[, start[, end]])
返回子串 sub 在 [start, end] 范围内非重叠出现的次数。 可选参数 startend 被解释为切片符号。
str.encode(encoding='utf-8', errors='strict')

将字符串的编码版本作为字节对象返回。 默认编码为 'utf-8'。 可以给出 errors 来设置不同的错误处理方案。 errors 的默认值为 'strict',这意味着编码错误会引发 UnicodeError。 其他可能的值是 'ignore''replace''xmlcharrefreplace''backslashreplace' 和通过 codecs.register_error() 注册的任何其他名称,请参阅部分 错误处理程序 。 有关可能的编码列表,请参阅 标准编码 部分。

默认情况下,不检查 errors 参数以获得最佳性能,而仅在第一个编码错误时使用。 启用Python开发模式,或使用调试版本检查错误

3.1 版更改: 添加了对关键字参数的支持。

在 3.9 版更改:现在在开发模式和 调试模式 中检查 错误

str.endswith(suffix[, start[, end]])
如果字符串以指定的 后缀 结尾,则返回 True,否则返回 Falsesuffix 也可以是要查找的后缀元组。 使用可选的 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]])

返回字符串中的最低索引,其中在切片 s[start:end] 中找到子字符串 sub。 可选参数 startend 被解释为切片符号。 如果未找到 sub,则返回 -1

笔记

只有在需要知道 sub 的位置时,才应使用 find() 方法。 要检查 sub 是否是子字符串,请使用 in 运算符:

>>> 'Py' in 'Python'
True
str.format(*args, **kwargs)

执行字符串格式化操作。 调用此方法的字符串可以包含由大括号 {} 分隔的文字文本或替换字段。 每个替换字段包含位置参数的数字索引或关键字参数的名称。 返回字符串的副本,其中每个替换字段都替换为相应参数的字符串值。

>>> "The sum of 1 + 2 is {0}".format(1+2)
'The sum of 1 + 2 is 3'

有关可以在格式字符串中指定的各种格式选项的说明,请参阅 格式字符串语法

笔记

使用 n 类型格式化数字(intfloatcomplexdecimal.Decimal 和子类)时(例如:'{:n}'.format(1234)),该函数将 LC_CTYPE 语言环境临时设置为 LC_NUMERIC 语言环境以解码 decimal_pointthousands_sep 字段X275X] 如果它们是非 ASCII 或长度超过 1 个字节,并且 LC_NUMERIC 区域设置与 LC_CTYPE 区域设置不同。 此临时更改会影响其他线程。

3.7 版更改: 格式化数字时,在某些情况下,该函数会将 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 标准中定义的“字母”属性不同。
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 是否为保留标识符,如 defclass

例子:

>>> from keyword import iskeyword

>>> 'hello'.isidentifier(), iskeyword('hello')
True, False
>>> 'def'.isidentifier(), iskeyword('def')
True, True
str.islower()
如果字符串中所有大小写字符 4 都是小写且至少有一个大小写字符,则返回 True,否则返回 False
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.stdoutsys.stderr 的字符串无关。)
str.isspace()

如果字符串中只有空格字符且至少有一个字符,则返回 True,否则返回 False

一个字符是 whitespace 如果在 Unicode 字符数据库(见 unicodedata)中,它的一般类别是 Zs(“分隔符,空格”),或者它的双向类是 WSBS 之一。

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])
在长度为 宽度 的字符串中返回左对齐的字符串。 填充是使用指定的 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])
返回所有出现的子字符串 old 替换为 new 的字符串副本。 如果给出了可选参数 count,则仅替换第一个 count 次出现。
str.rfind(sub[, start[, end]])
返回字符串中找到子字符串 sub 的最高索引,这样 sub 包含在 s[start:end] 中。 可选参数 startend 被解释为切片符号。 失败时返回 -1
str.rindex(sub[, start[, end]])
rfind() 类似,但在未找到子字符串 sub 时引发 ValueError
str.rjust(width[, fillchar])
在长度为 宽度 的字符串中返回右对齐的字符串。 填充是使用指定的 fillchar(默认为 ASCII 空间)完成的。 如果 width 小于或等于 len(s),则返回原始字符串。
str.rpartition(sep)
在最后一次出现 sep 时拆分字符串,并返回一个 3 元组,其中包含分隔符之前的部分、分隔符本身和分隔符之后的部分。 如果未找到分隔符,则返回一个包含两个空字符串的 3 元组,后跟字符串本身。
str.rsplit(sep=None, maxsplit=- 1)
返回字符串中单词的列表,使用 sep 作为分隔符字符串。 如果给出 maxsplit,则最多完成 maxsplit 次分割, 最右边的 次分割。 如果未指定 sepNone,则任何空白字符串都是分隔符。 除了从右侧拆分外,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', '']

如果未指定 sepNone,则应用不同的拆分算法:将连续空白的运行视为单个分隔符,结果将不包含开头或如果字符串有前导或尾随空格,则结束。 因此,用 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])

返回字符串中的行列表,在行边界处断开。 除非给出 keepends 并且为真,否则结果列表中不包含换行符。

此方法在以下行边界上拆分。 特别是,边界是 通用换行符 的超集。

表示

描述

\n

换行

\r

回车

\r\n

回车 + 换行

\v\x0b

线制表

\f\x0c

换页

\x1c

文件分隔符

\x1d

组分隔符

\x1e

记录分隔符

\x85

下一行(C1 控制代码)

\u2028

行分隔符

\u2029

段落分隔符

3.2 版更改: \v\f 添加到线边界列表。

例如:

>>> 'ab c\n\nde fg\rkl\r\n'.splitlines()
['ab c', '', 'de fg', 'kl']
>>> 'ab c\n\nde fg\rkl\r\n'.splitlines(keepends=True)
['ab c\n', '\n', 'de fg\r', 'kl\r\n']

与给定分隔符字符串 sep 时的 split() 不同,此方法返回空字符串的空列表,并且终端换行不会导致额外的行:

>>> "".splitlines()
[]
>>> "One line\n".splitlines()
['One line']

为了比较,split('\n') 给出:

>>> ''.split('\n')
['']
>>> 'Two lines\n'.split('\n')
['Two lines', '']
str.startswith(prefix[, start[, end]])
如果字符串以 前缀 开头,则返回 True,否则返回 Falseprefix 也可以是要查找的前缀元组。 使用可选的 start,测试字符串从该位置开始。 使用可选的 end,停止在该位置比较字符串。
str.strip([chars])

返回删除前导和尾随字符的字符串副本。 chars 参数是一个字符串,指定要删除的字符集。 如果省略或 Nonechars 参数默认为删除空格。 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"

可以使用正则表达式构造撇号的解决方法:

>>> 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 序数或字符串,将字符映射到一个或多个其他字符; return None,删除返回字符串中的字符; 或引发 LookupError 异常,将字符映射到自身。

您可以使用 str.maketrans() 从不同格式的字符到字符映射创建转换映射。

另请参阅 codecs 模块以获取更灵活的自定义字符映射方法。

str.upper()

返回所有大小写字符 4 转换为大写的字符串副本。 注意 s.upper().isupper() 可能是 False 如果 s 包含未区分大小写的字符或者如果结果字符的 Unicode 类别不是“Lu”(字母,大写),但是例如 “Lt”(字母,标题)。

使用的大写算法在 Unicode 标准的第 3.13 节中描述。

str.zfill(width)

返回用 ASCII '0' 数字填充的字符串的副本,以生成长度为 、宽度为 的字符串。 前导符号前缀 ('+'/'-') 是通过在 符号字符之后而不是之前插入填充 来处理的。 如果 width 小于或等于 len(s),则返回原始字符串。

例如:

>>> "42".zfill(5)
'00042'
>>> "-42".zfill(5)
'-0042'


printf 样式的字符串格式

笔记

此处描述的格式化操作表现出各种怪癖,这些怪癖会导致许多常见错误(例如无法正确显示元组和字典)。 使用较新的 格式化字符串文字str.format() 接口或 模板字符串 可能有助于避免这些错误。 这些替代方案中的每一个都提供了自己的权衡和简单性、灵活性和/或可扩展性的好处。


字符串对象有一个独特的内置操作:% 操作符(取模)。 这也称为字符串 formattinginterpolation 运算符。 给定 format % values(其中 format 是一个字符串),format 中的 % 转换规范被替换为 值的零个或多个元素[ X161X]。 效果类似于在C语言中使用sprintf()

如果 format 需要单个参数,则 values 可能是单个非元组对象。 5 否则,values 必须是一个元组,它的项数正好是格式字符串指定的项数,或者是单个映射对象(例如,字典)。

转换说明符包含两个或更多字符,并具有以下组件,必须按此顺序出现:

  1. '%' 字符,标记说明符的开始。
  2. 映射键(可选),由带括号的字符序列组成(例如,(somename))。
  3. 转换标志(可选),影响某些转换类型的结果。
  4. 最小字段宽度(可选)。 如果指定为 '*'(星号),则从 values 中元组的下一个元素读取实际宽度,并且要转换的对象在最小字段宽度和可选精度之后。
  5. 精度(可选),以 '.'(点)后跟精度的形式给出。 如果指定为 '*'(星号),则从 values 中元组的下一个元素读取实际精度,并且要转换的值在精度之后。
  6. 长度修饰符(可选)。
  7. 转换类型。

当正确的参数是字典(或其他映射类型)时,字符串 中的格式必须 包括一个带括号的映射键,该键插入到该字典中,紧跟在 '%' 字符之后。 映射键从映射中选择要格式化的值。 例如:

>>> print('%(language)s has %(number)03d quote types.' %
...       {'language': "Python", "number": 2})
Python has 002 quote types.

在这种情况下,格式中不能出现 * 说明符(因为它们需要顺序参数列表)。

转换标志字符为:

旗帜 意义
'#' 值转换将使用“替代形式”(定义如下)。
'0' 转换将为数值填充零。
'-' 转换后的值左调整(如果两者都给出,则覆盖 '0' 转换)。
' ' (一个空格)在有符号转换产生的正数(或空字符串)之前应该留一个空格。
'+' 符号字符('+''-')将在转换之前(覆盖“空格”标志)。

长度修饰符(hlL)可能存在,但被忽略,因为它不是 Python 所必需的——例如 %ld%d 相同。

转换类型有:

转换 意义 笔记
'd' 有符号整数十进制。
'i' 有符号整数十进制。
'o' 有符号八进制值。 (1)
'u' 过时类型 – 与 'd' 相同。 (6)
'x' 有符号的十六进制(小写)。 (2)
'X' 有符号的十六进制(大写)。 (2)
'e' 浮点指数格式(小写)。 (3)
'E' 浮点指数格式(大写)。 (3)
'f' 浮点十进制格式。 (3)
'F' 浮点十进制格式。 (3)
'g' 浮点格式。 如果指数小于 -4 或不小于精度,则使用小写指数格式,否则使用十进制格式。 (4)
'G' 浮点格式。 如果指数小于 -4 或不小于精度,则使用大写指数格式,否则使用十进制格式。 (4)
'c' 单字符(接受整数或单字符串)。
'r' 字符串(使用 repr() 转换任何 Python 对象)。 (5)
's' 字符串(使用 str() 转换任何 Python 对象)。 (5)
'a' 字符串(使用 ascii() 转换任何 Python 对象)。 (5)
'%' 不转换任何参数,结果中会出现 '%' 字符。

笔记:

  1. 替代形式导致在第一个数字之前插入一个前导八进制说明符 ('0o')。

  2. 替代形式导致在第一个数字之前插入前导 '0x''0X'(取决于是否使用 'x''X' 格式)。

  3. 替代形式导致结果始终包含小数点,即使其后没有数字。

    精度决定小数点后的位数,默认为 6。

  4. 替代形式导致结果始终包含小数点,并且不会像其他情况那样删除尾随零。

    精度决定小数点前后的有效位数,默认为 6。

  5. 如果精度为 N,则输出将被截断为 N 字符。

  6. PEP 237

由于 Python 字符串具有明确的长度,因此 %s 转换不假定 '\0' 是字符串的结尾。

3.1 版更改:绝对值超过 1e50 的数字的 %f 转换不再被 %g 转换替换。


二进制序列类型 — bytes、bytearray、memoryview

用于操作二进制数据的核心内置类型是 bytesbytearray。 它们由 memoryview 支持,它使用 缓冲协议 来访问其他二进制对象的内存,而无需进行复制。

array 模块支持基本数据类型的高效存储,如 32 位整数和 IEEE754 双精度浮点值。

字节对象

字节对象是不可变的单字节序列。 由于许多主要的二进制协议都基于 ASCII 文本编码,因此字节对象提供了几种方法,这些方法仅在处理 ASCII 兼容数据时才有效,并以各种其他方式与字符串对象密切相关。

class bytes([source[, encoding[, errors]]])

首先,字节文字的语法与字符串文字的语法大致相同,只是添加了 b 前缀:

  • 单引号:b'still allows embedded "double" quotes'

  • 双引号:b"still allows embedded 'single' quotes"

  • 三重引用:b3 single quotesb"""3 double quotes"""

字节文字中只允许使用 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() 现在支持可选的 sepbytes_per_sep 参数,以在十六进制输出中的字节之间插入分隔符.

由于字节对象是整数序列(类似于元组),对于字节对象 bb[0] 将是一个整数,而 b[0:1] 将是一个字节对象长度 1。 (这与文本字符串形成对比,其中索引和切片都会产生长度为 1 的字符串)

字节对象的表示使用文字格式(b'...'),因为它通常比例如更有用 bytes([46, 46, 46])。 您始终可以使用 list(b) 将字节对象转换为整数列表。

笔记

对于 Python 2.x 用户:在 Python 2.x 系列中,允许在 8 位字符串(2.x 提供的与内置二进制数据类型最接近的东西)和 Unicode 字符串之间进行各种隐式转换。 这是一种向后兼容的解决方法,以解决 Python 最初仅支持 8 位文本,而 Unicode 文本是后来添加的这一事实。 在 Python 3.x 中,那些隐式转换消失了——8 位二进制数据和 Unicode 文本之间的转换必须是显式的,字节和字符串对象将始终比较不相等。


字节数组对象

bytearray 对象是 bytes 对象的可变对应物。

class bytearray([source[, encoding[, errors]]])

bytearray 对象没有专用的文字语法,而是始终通过调用构造函数来创建它们:

  • 创建一个空实例:bytearray()

  • 创建一个给定长度的零填充实例:bytearray(10)

  • 从整数迭代:bytearray(range(20))

  • 通过缓冲协议复制现有的二进制数据:bytearray(b'Hi!')

由于字节数组对象是可变的,因此除了 字节和字节数组操作 中描述的常见字节和字节数组操作之外,它们还支持 可变 序列操作。

另请参阅内置的 bytearray

由于 2 个十六进制数字精确对应一个字节,因此十六进制数是描述二进制数据的常用格式。 因此, bytearray 类型有一个额外的类方法来读取该格式的数据:

classmethod fromhex(string)

这个 bytearray 类方法返回 bytearray 对象,解码给定的字符串对象。 该字符串必须包含每个字节的两个十六进制数字,ASCII 空格将被忽略。

>>> bytearray.fromhex('2Ef0 F1f2  ')
bytearray(b'.\xf0\xf1\xf2')

3.7 版更改: bytearray.fromhex() 现在跳过字符串中的所有 ASCII 空格,而不仅仅是空格。

存在一个反向转换函数,用于将 bytearray 对象转换为其十六进制表示。

hex([sep[, bytes_per_sep]])

为实例中的每个字节返回一个包含两个十六进制数字的字符串对象。

>>> bytearray(b'\xf0\xf1\xf2').hex()
'f0f1f2'

3.5 版中的新功能。

3.8 版更改: 类似于 bytes.hex()bytearray.hex() 现在支持可选的 sepbytes_per_sep 参数,用于在十六进制输出中的字节之间插入分隔符。

由于字节数组对象是整数序列(类似于列表),对于字节数组对象 bb[0] 将是一个整数,而 b[0:1] 将是一个字节数组对象长度 1。 (这与文本字符串形成对比,其中索引和切片都会产生长度为 1 的字符串)

bytearray 对象的表示使用字节文字格式 (bytearray(b'...')),因为它通常比 eg 更有用 bytearray([46, 46, 46])。 您始终可以使用 list(b) 将 bytearray 对象转换为整数列表。


字节和字节数组操作

bytes 和 bytearray 对象都支持 common 序列操作。 它们不仅与相同类型的操作数互操作,而且与任何 字节类对象 互操作。 由于这种灵活性,它们可以在操作中自由混合而不会导致错误。 但是,结果的返回类型可能取决于操作数的顺序。

笔记

bytes 和 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]])

返回 [start, end] 范围内子序列 sub 的非重叠出现次数。 可选参数 startend 被解释为切片符号。

要搜索的子序列可以是任何 bytes-like object 或 0 到 255 范围内的整数。

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'

前缀可以是任何字节类对象

笔记

此方法的字节数组版本 就地操作 - 它总是生成一个新对象,即使没有进行任何更改。

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'

后缀 可以是任何 字节类对象

笔记

此方法的字节数组版本 就地操作 - 它总是生成一个新对象,即使没有进行任何更改。

3.9 版中的新功能。

bytes.decode(encoding='utf-8', errors='strict')
bytearray.decode(encoding='utf-8', errors='strict')

返回从给定字节解码的字符串。 默认编码为 'utf-8'。 可以给出 errors 来设置不同的错误处理方案。 errors 的默认值为 'strict',这意味着编码错误会引发 UnicodeError。 其他可能的值是 'ignore''replace' 和通过 codecs.register_error() 注册的任何其他名称,请参阅部分 Error Handlers。 有关可能的编码列表,请参阅 标准编码 部分。

默认情况下,不检查 errors 参数以获得最佳性能,而仅在第一个解码错误时使用。 启用Python开发模式,或使用调试版本检查错误

笔记

encoding 参数传递给 str 允许直接解码任何 bytes-like object,而无需创建临时字节或 bytearray 对象。

3.1 版更改: 添加了对关键字参数的支持。

在 3.9 版更改:现在在开发模式和 调试模式 中检查 错误

bytes.endswith(suffix[, start[, end]])
bytearray.endswith(suffix[, start[, end]])

如果二进制数据以指定的 后缀 结尾,则返回 True,否则返回 Falsesuffix 也可以是要查找的后缀元组。 使用可选的 start,从该位置开始测试。 使用可选的 end,在该位置停止比较。

要搜索的后缀可以是任何 bytes-like object

bytes.find(sub[, start[, end]])
bytearray.find(sub[, start[, end]])

返回数据中找到子序列 sub 的最低索引,使得 sub 包含在切片 s[start:end] 中。 可选参数 startend 被解释为切片符号。 如果未找到 sub,则返回 -1

要搜索的子序列可以是任何 bytes-like object 或 0 到 255 范围内的整数。

笔记

只有在需要知道 sub 的位置时,才应使用 find() 方法。 要检查 sub 是否是子字符串,请使用 in 运算符:

>>> b'Py' in b'Python'
True

3.3 版更改: 也接受 0 到 255 范围内的整数作为子序列。

bytes.index(sub[, start[, end]])
bytearray.index(sub[, start[, end]])

find() 类似,但在未找到子序列时引发 ValueError

要搜索的子序列可以是任何 bytes-like object 或 0 到 255 范围内的整数。

3.3 版更改: 也接受 0 到 255 范围内的整数作为子序列。

bytes.join(iterable)

bytearray.join(iterable)

返回一个 bytes 或 bytearray 对象,它是 iterable 中二进制数据序列的串联。 如果 iterable 中的任何值不是 bytes-like objects,包括 str 对象,则会引发 TypeError。 元素之间的分隔符是提供此方法的字节或字节数组对象的内容。
static bytes.maketrans(from, to)
static bytearray.maketrans(from, to)

这个静态方法返回一个可用于 bytes.translate() 的转换表,它将 from 中的每个字符映射到 to 中相同位置的字符; fromto 必须都是 bytes-like objects 并且具有相同的长度。

3.1 版中的新功能。

bytes.partition(sep)
bytearray.partition(sep)

在第一次出现 sep 时拆分序列,并返回一个 3 元组,其中包含分隔符之前的部分、分隔符本身或其字节数组副本以及分隔符之后的部分。 如果未找到分隔符,则返回一个包含原始序列副本的 3 元组,后跟两个空字节或 bytearray 对象。

要搜索的分隔符可以是任何 bytes-like object

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] 中。 可选参数 startend 被解释为切片符号。 失败时返回 -1

要搜索的子序列可以是任何 bytes-like object 或 0 到 255 范围内的整数。

3.3 版更改: 也接受 0 到 255 范围内的整数作为子序列。

bytes.rindex(sub[, start[, end]])
bytearray.rindex(sub[, start[, end]])

rfind() 类似,但在未找到子序列 sub 时引发 ValueError

要搜索的子序列可以是任何 bytes-like object 或 0 到 255 范围内的整数。

3.3 版更改: 也接受 0 到 255 范围内的整数作为子序列。

bytes.rpartition(sep)
bytearray.rpartition(sep)

在最后一次出现 sep 时拆分序列,并返回一个 3 元组,其中包含分隔符之前的部分、分隔符本身或其字节数组副本以及分隔符之后的部分。 如果未找到分隔符,则返回一个包含两个空字节或字节数组对象的 3 元组,后跟原始序列的副本。

要搜索的分隔符可以是任何 bytes-like object

bytes.startswith(prefix[, start[, end]])
bytearray.startswith(prefix[, start[, end]])

如果二进制数据以指定的 前缀 开头,则返回 True,否则返回 Falseprefix 也可以是要查找的前缀元组。 使用可选的 start,从该位置开始测试。 使用可选的 end,在该位置停止比较。

要搜索的前缀可以是任何 字节的对象

bytes.translate(table, /, delete=b)
bytearray.translate(table, /, delete=b)

返回 bytes 或 bytearray 对象的副本,其中删除了可选参数 delete 中出现的所有字节,剩余的字节已通过给定的转换表映射,该转换表必须是长度为 256 的字节对象。

您可以使用 bytes.maketrans() 方法来创建转换表。

对于仅删除字符的翻译,将 table 参数设置为 None

>>> b'read this short text'.translate(None, b'aeiou')
b'rd ths shrt txt'

在 3.6 版更改:现在支持 delete 作为关键字参数。

字节和字节数组对象上的以下方法具有默认行为,假设使用 ASCII 兼容的二进制格式,但仍然可以通过传递适当的参数与任意二进制数据一起使用。 请注意,本节中的所有 bytearray 方法都 不是 就地操作,而是生成新对象。

bytes.center(width[, fillbyte])
bytearray.center(width[, fillbyte])

返回以长度 宽度 为中心的对象副本。 填充是使用指定的 fillbyte(默认为 ASCII 空间)完成的。 对于 bytes 对象,如果 width 小于或等于 len(s),则返回原始序列。

笔记

此方法的字节数组版本 就地操作 - 它总是生成一个新对象,即使没有进行任何更改。

bytes.ljust(width[, fillbyte])
bytearray.ljust(width[, fillbyte])

以长度 宽度 的序列返回左对齐对象的副本。 填充是使用指定的 fillbyte(默认为 ASCII 空间)完成的。 对于 bytes 对象,如果 width 小于或等于 len(s),则返回原始序列。

笔记

此方法的字节数组版本 就地操作 - 它总是生成一个新对象,即使没有进行任何更改。

bytes.lstrip([chars])
bytearray.lstrip([chars])

返回删除指定前导字节的序列副本。 chars 参数是一个二进制序列,指定要删除的字节值集 - 该名称指的是此方法通常与 ASCII 字符一起使用的事实。 如果省略或 Nonechars 参数默认为删除 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!'

笔记

此方法的字节数组版本 就地操作 - 它总是生成一个新对象,即使没有进行任何更改。

bytes.rjust(width[, fillbyte])
bytearray.rjust(width[, fillbyte])

返回按长度 宽度 序列右对齐的对象副本。 填充是使用指定的 fillbyte(默认为 ASCII 空间)完成的。 对于 bytes 对象,如果 width 小于或等于 len(s),则返回原始序列。

笔记

此方法的字节数组版本 就地操作 - 它总是生成一个新对象,即使没有进行任何更改。

bytes.rsplit(sep=None, maxsplit=- 1)

bytearray.rsplit(sep=None, maxsplit=- 1)

将二进制序列拆分为相同类型的子序列,使用 sep 作为分隔符字符串。 如果给出 maxsplit,则最多完成 maxsplit 次分割, 最右边的 次分割。 如果未指定 sepNone,则任何仅由 ASCII 空格组成的子序列都是分隔符。 除了从右侧拆分外,rsplit() 的行为类似于 split(),下面将对其进行详细描述。
bytes.rstrip([chars])
bytearray.rstrip([chars])

返回删除了指定尾随字节的序列副本。 chars 参数是一个二进制序列,指定要删除的字节值集 - 该名称指的是此方法通常与 ASCII 字符一起使用的事实。 如果省略或 Nonechars 参数默认为删除 ASCII 空格。 chars 参数不是后缀; 相反,它的值的所有组合都被剥离了:

>>> b'   spacious   '.rstrip()
b'   spacious'
>>> b'mississippi'.rstrip(b'ipz')
b'mississ'

要删除的字节值的二进制序列可以是任何 bytes-like object。 请参阅 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)

将二进制序列拆分为相同类型的子序列,使用 sep 作为分隔符字符串。 如果给定 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 参数可以是任何 bytes-like object

例如:

>>> 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'']

如果未指定 sepNone,则应用不同的拆分算法:将连续 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 字符一起使用的事实。 如果省略或 Nonechars 参数默认为删除 ASCII 空格。 chars 参数不是前缀或后缀; 相反,它的值的所有组合都被剥离了:

>>> b'   spacious   '.strip()
b'spacious'
>>> b'www.example.com'.strip(b'cmowz.')
b'example'

要删除的字节值的二进制序列可以是任何 bytes-like object

笔记

此方法的字节数组版本 就地操作 - 它总是生成一个新对象,即使没有进行任何更改。

以下字节和字节数组对象的方法假定使用 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'),则复制它并将当前列重置为零。 任何其他字节值都被原封不动地复制,并且无论打印时字节值的表示方式如何,当前列都会增加 1:

>>> 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。 有关“titlecase”定义的更多详细信息,请参见 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' 中的那些字节值。

笔记

此方法的字节数组版本 就地操作 - 它总是生成一个新对象,即使没有进行任何更改。

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']

与给定分隔符字符串 sep 时的 split() 不同,此方法返回空字符串的空列表,并且终端换行不会导致额外的行:

>>> b"".split(b'\n'), b"Two lines\n".split(b'\n')
([b''], [b'Two lines', b''])
>>> b"".splitlines(), b"One line\n".splitlines()
([], [b'One line'])
bytes.swapcase()
bytearray.swapcase()

返回序列的副本,其中所有小写 ASCII 字符都转换为相应的大写字母,反之亦然。

例如:

>>> b'Hello World'.swapcase()
b'hELLO wORLD'

小写 ASCII 字符是序列 b'abcdefghijklmnopqrstuvwxyz' 中的那些字节值。 大写 ASCII 字符是序列 b'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 中的那些字节值。

str.swapcase() 不同,二进制版本始终是 bin.swapcase().swapcase() == bin。 大小写转换在 ASCII 中是对称的,即使对于任意 Unicode 代码点通常不是这样。

笔记

此方法的字节数组版本 就地操作 - 它总是生成一个新对象,即使没有进行任何更改。

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."

笔记

此方法的字节数组版本 就地操作 - 它总是生成一个新对象,即使没有进行任何更改。

bytes.upper()
bytearray.upper()

返回序列的副本,其中所有小写 ASCII 字符都转换为相应的大写字母。

例如:

>>> b'Hello World'.upper()
b'HELLO WORLD'

小写 ASCII 字符是序列 b'abcdefghijklmnopqrstuvwxyz' 中的那些字节值。 大写 ASCII 字符是序列 b'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 中的那些字节值。

笔记

此方法的字节数组版本 就地操作 - 它总是生成一个新对象,即使没有进行任何更改。

bytes.zfill(width)
bytearray.zfill(width)

返回用 ASCII b'0' 数字填充的序列的副本,以制作长度为 宽度 的序列。 前导符号前缀 (b'+'/b'-') 是通过在 符号字符之后而不是之前插入填充 来处理的。 对于 bytes 对象,如果 width 小于或等于 len(seq),则返回原始序列。

例如:

>>> b"42".zfill(5)
b'00042'
>>> b"-42".zfill(5)
b'-0042'

笔记

此方法的字节数组版本 就地操作 - 它总是生成一个新对象,即使没有进行任何更改。


printf 风格的字节格式

笔记

此处描述的格式化操作表现出各种怪癖,这些怪癖会导致许多常见错误(例如无法正确显示元组和字典)。 如果打印的值可能是元组或字典,请将其包装在元组中。


字节对象 (bytes/bytearray) 有一个独特的内置操作:% 运算符(模)。 这也称为字节 格式插值 运算符。 给定 format % values(其中 format 是字节对象),format 中的 % 转换规范被替换为 值的零个或多个元素。 效果类似于在C语言中使用sprintf()

如果 format 需要单个参数,则 values 可能是单个非元组对象。 5 否则,values 必须是一个元组,其项目数与格式字节对象或单个映射对象(例如,字典)所指定的项目数完全相同。

转换说明符包含两个或更多字符,并具有以下组件,必须按此顺序出现:

  1. '%' 字符,标记说明符的开始。
  2. 映射键(可选),由带括号的字符序列组成(例如,(somename))。
  3. 转换标志(可选),影响某些转换类型的结果。
  4. 最小字段宽度(可选)。 如果指定为 '*'(星号),则从 values 中元组的下一个元素读取实际宽度,并且要转换的对象在最小字段宽度和可选精度之后。
  5. 精度(可选),以 '.'(点)后跟精度的形式给出。 如果指定为 '*'(星号),则从 values 中元组的下一个元素读取实际精度,并且要转换的值在精度之后。
  6. 长度修饰符(可选)。
  7. 转换类型。

当正确的参数是字典(或其他映射类型)时,字节对象 中的格式必须 包括一个带括号的映射键,该键插入在 '%' 字符之后立即插入的字典中。 映射键从映射中选择要格式化的值。 例如:

>>> print(b'%(language)s has %(number)03d quote types.' %
...       {b'language': b"Python", b"number": 2})
b'Python has 002 quote types.'

在这种情况下,格式中不能出现 * 说明符(因为它们需要顺序参数列表)。

转换标志字符为:

旗帜 意义
'#' 值转换将使用“替代形式”(定义如下)。
'0' 转换将为数值填充零。
'-' 转换后的值左调整(如果两者都给出,则覆盖 '0' 转换)。
' ' (一个空格)在有符号转换产生的正数(或空字符串)之前应该留一个空格。
'+' 符号字符('+''-')将在转换之前(覆盖“空格”标志)。

长度修饰符(hlL)可能存在,但被忽略,因为它不是 Python 所必需的——例如 %ld%d 相同。

转换类型有:

转换 意义 笔记
'd' 有符号整数十进制。
'i' 有符号整数十进制。
'o' 有符号八进制值。 (1)
'u' 过时类型 – 与 'd' 相同。 (8)
'x' 有符号的十六进制(小写)。 (2)
'X' 有符号的十六进制(大写)。 (2)
'e' 浮点指数格式(小写)。 (3)
'E' 浮点指数格式(大写)。 (3)
'f' 浮点十进制格式。 (3)
'F' 浮点十进制格式。 (3)
'g' 浮点格式。 如果指数小于 -4 或不小于精度,则使用小写指数格式,否则使用十进制格式。 (4)
'G' 浮点格式。 如果指数小于 -4 或不小于精度,则使用大写指数格式,否则使用十进制格式。 (4)
'c' 单字节(接受整数或单字节对象)。
'b' 字节(任何遵循 缓冲区协议 或具有 __bytes__() 的对象)。 (5)
's' 's''b' 的别名,只能用于 Python2/3 代码库。 (6)
'a' 字节(使用 repr(obj).encode('ascii','backslashreplace) 转换任何 Python 对象)。 (5)
'r' 'r''a' 的别名,只能用于 Python2/3 代码库。 (7)
'%' 不转换任何参数,结果中会出现 '%' 字符。

笔记:

  1. 替代形式导致在第一个数字之前插入一个前导八进制说明符 ('0o')。

  2. 替代形式导致在第一个数字之前插入前导 '0x''0X'(取决于是否使用 'x''X' 格式)。

  3. 替代形式导致结果始终包含小数点,即使其后没有数字。

    精度决定小数点后的位数,默认为 6。

  4. 替代形式导致结果始终包含小数点,并且不会像其他情况那样删除尾随零。

    精度决定小数点前后的有效位数,默认为 6。

  5. 如果精度为 N,则输出将被截断为 N 字符。

  6. b'%s' 已弃用,但不会在 3.x 系列中移除。

  7. b'%r' 已弃用,但不会在 3.x 系列中移除。

  8. PEP 237

笔记

此方法的字节数组版本 就地操作 - 它总是生成一个新对象,即使没有进行任何更改。


也可以看看

PEP 461 - 将 % f 格式添加到字节和字节数组


3.5 版中的新功能。


内存视图

memoryview 对象允许 Python 代码访问支持 缓冲协议 的对象的内部数据而无需复制。

class memoryview(object)

创建一个引用 对象内存视图object 必须支持缓冲协议。 支持缓冲协议的内置对象包括 bytesbytearray

memoryview 具有 element 的概念,它是由原始 object 处理的原子内存单元。 对于许多简单类型,例如 bytesbytearray,元素是单个字节,但其他类型,例如 array.array 可能有更大的元素。

len(view)等于tolist的长度。 如果view.ndim = 0,则长度为1。 如果是view.ndim = 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有几种方法:

__eq__(exporter)

如果内存视图和 PEP 3118 导出器的形状相同,并且当使用 struct 解释操作数各自的格式代码时所有对应的值都相同,则它们是相同的句法。

对于 tolist() 当前支持的 struct 格式字符串的子集,如果 v.tolist() == w.tolist()vw 相等:

>>> 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 暗示 v == w

3.3 版本变化: 之前的版本比较了原始内存,不考虑项目格式和逻辑数组结构。

tobytes(order=None)

将缓冲区中的数据作为字节串返回。 这相当于在 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=Noneorder='C' 相同。

hex([sep[, bytes_per_sep]])

为缓冲区中的每个字节返回一个包含两个十六进制数字的字符串对象。

>>> m = memoryview(b"abc")
>>> m.hex()
'616263'

3.5 版中的新功能。

3.8 版更改: 类似于 bytes.hex()memoryview.hex() 现在支持可选的 sepbytes_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]

3.3 版更改: tolist() 现在支持 struct 模块语法中的所有单字符本机格式以及多维表示。

toreadonly()

返回 memoryview 对象的只读版本。 原始的 memoryview 对象不变。

>>> m = memoryview(bytearray(b'abc'))
>>> mm = m.toreadonly()
>>> mm.tolist()
[89, 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],这意味着结果视图将是一维的。 返回值是一个新的内存视图,但缓冲区本身没有被复制。 支持的转换是 1D -> C-contiguous 和 C-contiguous -> 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

将一维/无符号字节转换为一维/字符:

>>> b = bytearray(b'zyz')
>>> x = memoryview(b)
>>> x[0] = b'a'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: memoryview: invalid value for format "B"
>>> y = x.cast('c')
>>> y[0] = b'a'
>>> b
bytearray(b'ayz')

将 1D/bytes 转换为 3D/ints 到 1D/signed char:

>>> import struct
>>> buf = struct.pack("i"*12, *list(range(12)))
>>> x = memoryview(buf)
>>> y = x.cast('i', shape=[2,2,3])
>>> y.tolist()
[[[0, 1, 2], [3, 4, 5]], [[6, 7, 8], [9, 10, 11]]]
>>> y.format
'i'
>>> y.itemsize
4
>>> len(y)
2
>>> y.nbytes
48
>>> z = y.cast('b')
>>> z.format
'b'
>>> z.itemsize
1
>>> len(z)
48
>>> z.nbytes
48

将 1D/unsigned long 转换为 2D/unsigned long:

>>> buf = struct.pack("L"*6, *list(range(6)))
>>> x = memoryview(buf)
>>> y = x.cast('L', shape=[2,3])
>>> len(y)
2
>>> y.nbytes
48
>>> y.tolist()
[[0, 1, 2], [3, 4, 5]]

3.3 版中的新功能。

3.5 版更改: 转换为字节视图时不再限制源格式。

还有几个只读属性可用:

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 模块样式中)的字符串。 内存视图可以从具有任意格式字符串的导出器创建,但某些方法(例如 tolist()) 仅限于原生单元素格式。

3.3 版更改: 格式 'B' 现在根据 struct 模块语法进行处理。 这意味着memoryview(b'abc')[0] == b'abc'[0] == 97

itemsize

memoryview 的每个元素的大小(以字节为单位):

>>> import array, struct
>>> m = memoryview(array.array('H', [32000, 32001, 32002]))
>>> m.itemsize
2
>>> m[0]
32000
>>> struct.calcsize('H') == m.itemsize
True
ndim

一个整数,指示内存表示的多维数组的维数。

shape

长度为 ndim 的整数元组,将内存的形状作为 N 维数组。

在 3.3 版更改: 当 ndim = 0 时,一个空元组而不是 None

strides

一个整数元组,长度为 ndim,给出访问数组每个维度的每个元素的字节大小。

在 3.3 版更改: 当 ndim = 0 时,一个空元组而不是 None

suboffsets

在内部用于 PIL 样式的数组。 该值仅供参考。

c_contiguous

指示内存是否为 C- 连续 的布尔值。

3.3 版中的新功能。

f_contiguous

一个布尔值,指示内存是否为 Fortran contiguous

3.3 版中的新功能。

contiguous

指示内存是否为 连续 的布尔值。

3.3 版中的新功能。


套装类型 — set、frozenset

set 对象是不同的 hashable 对象的无序集合。 常见用途包括成员资格测试、从序列中删除重复项以及计算交集、并集、差和对称差等数学运算。 (对于其他容器,请参阅内置的 dictlisttuple 类,以及 collections 模块。)

与其他集合一样,集合支持 [X37X]、len(set)for x in set。 作为一个无序集合,集合不记录元素位置或插入顺序。 因此,集合不支持索引、切片或其他类似序列的行为。

目前有两种内置设置类型,setfrozensetset 类型是可变的——可以使用 add()remove() 等方法更改内容。 由于它是可变的,它没有哈希值,不能用作字典键或另一个集合的元素。 frozenset 类型是不可变的和 hashable——它的内容在它被创建后不能改变; 因此,它可以用作字典键或另一个集合的元素。

除了 set 构造函数之外,还可以通过在大括号内放置一个逗号分隔的元素列表来创建非空集(不是frozensets),例如:{'jack', 'sjoerd'}

这两个类的构造函数的工作方式相同:

class set([iterable])
class frozenset([iterable])

返回一个新的 set 或frozenset 对象,其元素取自 iterable。 集合的元素必须是 hashable。 为了表示集合的集合,内部集合必须是 frozenset 对象。 如果未指定 iterable,则返回一个新的空集。

可以通过多种方式创建集合:

  • 在大括号内使用逗号分隔的元素列表:{'jack', 'sjoerd'}

  • 使用集合推导:{c for c in 'abracadabra' if c not in 'abc'}

  • 使用类型构造函数:set()set('foobar')set(['a', 'b', 'foo'])

setfrozenset 的实例提供以下操作:

len(s)

返回集合 s 中元素的数量(s 的基数)。

x in s

测试 xs 中的成员资格。

x not in s

s 中测试 x 是否为非会员。

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')

setfrozenset 都支持 set 设置比较。 两个集合相等当且仅当每个集合的每个元素都包含在另一个集合中(每个都是另一个的子集)。 一个集合小于另一个集合当且仅当第一个集合是第二个集合的一个真子集(是一个子集,但不相等)。 一个集合大于另一个集合当且仅当第一个集合是第二个集合的真超集(是一个超集,但不相等)。

set 的实例根据其成员与 frozenset 的实例进行比较。 例如,set('abc') == frozenset('abc') 返回 Trueset('abc') in set([frozenset('abc')]) 也是如此。

子集和相等比较不能推广到总排序函数。 例如,任意两个非空不相交集不相等,也不是彼此的子集,所以下面的all返回Falsea<ba==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 添加到集合中。

remove(elem)

从集合中移除元素 elem。 如果 elem 不包含在集合中,则引发 KeyError

discard(elem)

如果存在,则从集合中删除元素 elem

pop()

从集合中删除并返回任意元素。 如果集合为空,则引发 KeyError

clear()

从集合中删除所有元素。

请注意,update()intersection_update()difference_update()symmetric_difference_update() 方法的非运营商版本将接受任何可迭代对象作为参数。

请注意,__contains__()remove()discard() 方法的 elem 参数可能是一个集合。 为了支持搜索等效的frozenset,从elem 创建了一个临时的。


映射类型 — dict

mapping 对象将 hashable 值映射到任意对象。 映射是可变对象。 目前只有一种标准映射类型,即 字典 。 (对于其他容器,请参阅内置的 listsettuple 类,以及 collections 模块。)

字典的键是 几乎 任意值。 不是 hashable 的值,即包含列表、字典或其他可变类型(按值而不是按对象标识进行比较)的值不能用作键。 用于键的数字类型遵循数字比较的正常规则:如果两个数字比较相等(例如 11.0),那么它们可以互换使用以索引相同的字典条目。 (但是请注意,由于计算机将浮点数存储为近似值,因此将它们用作字典键通常是不明智的。)

可以通过在大括号内放置以逗号分隔的 key: value 对列表来创建字典,例如:{'jack': 4098, 'sjoerd': 4127}{4098: 'jack', 4127: 'sjoerd'},或通过 dict 构造函数.

class dict(**kwarg)
class dict(mapping, **kwarg)
class dict(iterable, **kwarg)

返回从可选位置参数和一组可能为空的关键字参数初始化的新字典。

可以通过多种方式创建字典:

  • 在大括号内使用逗号分隔的 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)

如果没有给出位置参数,则创建一个空字典。 如果给出了一个位置参数并且它是一个映射对象,则使用与映射对象相同的键值对创建一个字典。 否则,位置参数必须是 iterable 对象。 可迭代对象中的每个项目本身必须是一个恰好有两个对象的可迭代对象。 每个项目的第一个对象成为新字典中的键,第二个对象成为相应的值。 如果某个键出现多次,则该键的最后一个值将成为新字典中的相应值。

如果给出了关键字参数,则关键字参数及其值将添加到从位置参数创建的字典中。 如果要添加的键已经存在,则来自关键字参数的值将替换来自位置参数的值。

为了说明,以下示例都返回一个等于 {"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 不在地图中,则引发 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] 设置为

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])

使用 iterable 中的键和设置为 value 的值创建一个新字典。

fromkeys() 是一个返回新字典的类方法。 value 默认为 None。 所有的值都只引用一个实例,因此 value 是一个可变对象(例如空列表)通常没有意义。 要获得不同的值,请改用 dict comprehension

get(key[, default])

如果 key 在字典中,则返回 key 的值,否则返回 default。 如果未给出 default,则默认为 None,因此该方法永远不会引发 KeyError

items()

返回字典项目的新视图((key, value) 对)。 请参阅视图对象 文档。

keys()

返回字典键的新视图。 请参阅视图对象 文档。

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])

如果 key 在字典中,则返回其值。 如果不是,则插入值为 defaultkey 并返回 defaultdefault 默认为 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

使用 dother 的合并键和值创建一个新字典,它们必须都是字典。 当dother共享密钥时,other的值优先。

3.9 版中的新功能。

d |= other

使用来自 other 的键和值更新字典 d,这可能是 映射 或键/值对的 iterable。 当dother共享密钥时,other的值优先。

3.9 版中的新功能。

字典比较相等当且仅当它们具有相同的 (key, value) 对(无论排序如何)。 顺序比较 ('=', '>') 引发类型错误 .

字典保留插入顺序。 请注意,更新密钥不会影响顺序。 删除后添加的键插入最后。

>>> 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(): pairs = zip(d.values(), d.keys()) 创建 (value, key) 对。 创建相同列表的另一种方法是 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 版中的新功能。

键视图是类似设置的,因为它们的条目是唯一且可散列的。 如果所有值都是可散列的,因此 (key, value) 对是唯一且可散列的,那么项目视图也是类似集合的。 (值视图不被视为类集合,因为条目通常不是唯一的。)对于类集合视图,为抽象基类 collections.abc.Set 定义的所有操作都可用(对于例如,==<^)。

字典视图用法示例:

>>> dishes = {'eggs': 2, 'sausage': 1, 'bacon': 1, 'spam': 500}
>>> keys = dishes.keys()
>>> values = dishes.values()

>>> # iteration
>>> n = 0
>>> for val in values:
...     n += val
>>> print(n)
504

>>> # keys and values are iterated over in the same order (insertion order)
>>> list(keys)
['eggs', 'sausage', 'bacon', 'spam']
>>> list(values)
[2, 1, 1, 500]

>>> # view objects are dynamic and reflect dict changes
>>> del dishes['eggs']
>>> del dishes['sausage']
>>> list(keys)
['bacon', 'spam']

>>> # set operations
>>> keys & {'eggs', 'bacon', 'salad'}
{'bacon'}
>>> keys ^ {'sausage', 'juice'}
{'juice', 'sausage', 'bacon', 'spam'}

>>> # get back a read-only proxy for the original dictionary
>>> values.mapping
mappingproxy({'eggs': 2, 'sausage': 1, 'bacon': 1, 'spam': 500})
>>> values.mapping['spam']
500

上下文管理器类型

Python 的 with 语句支持由上下文管理器定义的运行时上下文的概念。 这是使用一对方法实现的,这些方法允许用户定义的类定义在语句体执行之前进入并在语句结束时退出的运行时上下文:

contextmanager.__enter__()

输入运行时上下文并返回此对象或与运行时上下文相关的另一个对象。 此方法返回的值使用此上下文管理器绑定到 with 语句的 as 子句中的标识符。

返回自身的上下文管理器的一个示例是 文件对象 。 文件对象从 __enter__() 返回自身,以允许将 open() 用作 with 语句中的上下文表达式。

返回相关对象的上下文管理器的一个示例是 decimal.localcontext() 返回的那个。 这些管理器将活动十进制上下文设置为原始十进制上下文的副本,然后返回该副本。 这允许对 with 语句主体中的当前十进制上下文进行更改,而不会影响 with 语句之外的代码。

contextmanager.__exit__(exc_type, exc_val, exc_tb)

退出运行时上下文并返回一个布尔标志,指示是否应抑制发生的任何异常。 如果在执行 with 语句的主体时发生异常,则参数包含异常类型、值和回溯信息。 否则,所有三个参数都是 None

从此方法返回真值将导致 with 语句抑制异常并继续执行紧跟在 with 语句之后的语句。 否则,此方法执行完毕后,异常将继续传播。 执行此方法期间发生的异常将替换 with 语句主体中发生的任何异常。

传入的异常永远不应该被显式地重新引发——相反,这个方法应该返回一个 false 值来指示该方法成功完成并且不想抑制引发的异常。 这允许上下文管理代码轻松检测 __exit__() 方法是否实际失败。

Python 定义了几个上下文管理器来支持简单的线程同步、文件或其他对象的提示关闭以及对活动十进制算术上下文的更简单操作。 除了上下文管理协议的实现之外,不会对特定类型进行特殊处理。 有关一些示例,请参阅 contextlib 模块。

Python 的 generators 和 contextlib.contextmanager 装饰器提供了一种方便的方法来实现这些协议。 如果生成器函数用 contextlib.contextmanager 装饰器装饰,它将返回一个实现必要的 __enter__()__exit__() 方法的上下文管理器,而不是由未修饰的生成器函数。

请注意,在 Python/C API 中 Python 对象的类型结构中,这些方法中的任何一个都没有特定的插槽。 想要定义这些方法的扩展类型必须将它们作为普通的 Python 可访问方法提供。 与设置运行时上下文的开销相比,单个类字典查找的开销可以忽略不计。


类型注释类型 — 通用别名、联合

type annotations 的核心内置类型是 Generic AliasUnion

通用别名类型

GenericAlias 对象是通过对一个类(通常是一个容器)下标来创建的,例如 list[int]。 它们主要用于 类型注释

通常,容器对象的订阅调用对象的方法__getitem__()。 但是,某些容器类的订阅可能会调用该类的类方法__class_getitem__()。 类方法 __class_getitem__() 应该返回一个 GenericAlias 对象。

笔记

如果存在类元类的 __getitem__(),它将优先于类中定义的 __class_getitem__()(更多信息请参见 PEP 560)细节)。


GenericAlias 对象充当 泛型类型 的代理,实现 参数化泛型 - 泛型的特定实例,为容器元素提供类型。

GenericAlias 对象的用户公开类型可以从 types.GenericAlias 访问并用于 isinstance() 检查。 它也可以用于直接创建 GenericAlias 对象。

T[X, Y, ...]

创建一个 GenericAlias 表示类型 T,其中包含 XY 等类型的元素,具体取决于所使用的 T。 例如,一个需要包含 float 元素的 list 的函数:

def average(values: list[float]) -> float:
    return sum(values) / len(values)

mapping 对象的另一个示例,使用 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()str() 显示参数化类型:

>>> repr(list[int])
'list[int]'

>>> str(list[int])
'list[int]'

泛型的 __getitem__() 方法将引发异常以禁止诸如 dict[str][str] 之类的错误:

>>> dict[str][str]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: There are no type variables left in dict[str]

但是,当使用 类型变量 时,此类表达式有效。 索引必须具有与 GenericAlias 对象的 __args__ 中类型变量项一样多的元素。

>>> from typing import TypeVar
>>> Y = TypeVar('Y')
>>> dict[str, Y][int]
dict[str, int]

通用别名的特殊属性

所有参数化泛型都实现了特殊的只读属性。

genericalias.__origin__

此属性指向非参数化泛型类:

>>> list[int].__origin__
<class 'list'>
genericalias.__args__

此属性是传递给泛型容器的原始 __class_getitem__() 的泛型类型的 元组 (可能长度为 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 主要用于静态类型检查。

也可以看看

  • PEP 585——“标准集合中的类型提示泛型”
  • __class_getitem__() – 用于实现参数化泛型。
  • Genericstyping 模块中的泛型。


3.9 版中的新功能。


联合类型

联合对象保存对多个 类型对象|(按位或)运算的值。 这些类型主要用于 类型注释 。 与 typing.Union 相比,联合类型表达式支持更清晰的类型提示语法。

X | Y | ...

定义一个联合对象,该对象包含 XY 等类型。 X | Y 表示 X 或 Y。 相当于typing.Union[X, Y]。 例如,以下函数需要类型为 intfloat 的参数:

def square(number: int | float) -> int | float:
    return number ** 2
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])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: isinstance() argument 2 cannot contain 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 | __main__.C

也可以看看

PEP 604 – PEP 提出 X | Y 语法和联合类型。


3.10 版中的新功能。


其他内置类型

解释器支持几种其他类型的对象。 其中大部分只支持一两个操作。

模块

模块上唯一的特殊操作是属性访问:m.name,其中 m 是一个模块,而 name 访问在 m' 中定义的名称s 符号表。 可以分配模块属性。 (请注意,import 语句严格来说并不是对模块对象的操作;import foo 不需要名为 foo 的模块对象存在,而是需要它对于某处名为 foo 的模块,需要一个(外部)定义。)

每个模块的一个特殊属性是 __dict__。 这是包含模块符号表的字典。 修改这个字典实际上会改变模块的符号表,但是直接赋值给__dict__属性是不可能的(你可以写m.__dict__['a'] = 1,它定义m.a1,但你不能写 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)

与函数对象一样,绑定方法对象支持获取任意属性。 但是,由于方法属性实际上存储在底层函数对象(meth.__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


省略号对象

该对象通常用于切片(参见 Slicings)。 它不支持特殊操作。 只有一个省略号对象,名为 Ellipsis(一个内置名称)。 type(Ellipsis)() 产生 Ellipsis 单例。

它写为 Ellipsis...


未实现的对象

当要求比较和二进制操作对它们不支持的类型进行操作时,将返回此对象。 有关详细信息,请参阅 比较 。 正好有一个 NotImplemented 对象。 type(NotImplemented)() 生成单例实例。

写成NotImplemented


布尔值

布尔值是两个常量对象 FalseTrue。 它们用于表示真值(尽管其他值也可以被视为假或真)。 在数字上下文中(例如,当用作算术运算符的参数时),它们的行为分别类似于整数 0 和 1。 内置函数 bool() 可用于将任何值转换为布尔值,前提是该值可以解释为真值(请参阅上面的 真值测试 部分)。

它们分别写为 FalseTrue


内部对象

有关此信息,请参阅 标准类型层次结构 。 它描述了堆栈帧对象、回溯对象和切片对象。


特殊属性

该实现向几个相关的对象类型添加了一些特殊的只读属性。 dir() 内置函数没有报告其中一些。

object.__dict__
用于存储对象(可写)属性的字典或其他映射对象。
instance.__class__
类实例所属的类。
class.__bases__
类对象的基类元组。
definition.__name__
类、函数、方法、描述符或生成器实例的名称。
definition.__qualname__

类、函数、方法、描述符或生成器实例的 限定名称

3.3 版中的新功能。

class.__mro__
此属性是在方法解析期间查找基类时要考虑的类的元组。
class.mro()
此方法可以被元类覆盖以自定义其实例的方法解析顺序。 它在类实例化时被调用,其结果存储在 __mro__ 中。
class.__subclasses__()

每个类都保存一个对其直接子类的弱引用列表。 此方法返回所有那些仍然存在的引用的列表。 该列表按定义顺序排列。 例子:

>>> int.__subclasses__()
[<class 'bool'>]

脚注

1
关于这些特殊方法的更多信息可以在 Python 参考手册 ( 基本定制 ) 中找到。
2
因此,列表 [1, 2] 被认为等于 [1.0, 2.0],对于元组也是如此。
3
他们必须有,因为解析器不能告诉操作数的类型。
4(1,2,3,4)
大小写字符是具有一般类别属性为“Lu”(字母,大写)、“Ll”(字母,小写)或“Lt”(字母,标题大写)之一的字符。
5(1,2)
因此,要仅格式化元组,您应该提供一个单例元组,其唯一元素是要格式化的元组。