Python 标准库
概述
- 可用性注释
内置函数
内置常量
- 由
site
模块添加的常量
- 由
内置类型
- 逻辑值检测
- 布尔运算 —-
and
,or
,not
- 比较运算
- 数字类型 —-
int
,float
,complex
- 迭代器类型
- 序列类型 —-
list
,tuple
,range
- 文本序列类型 —-
str
- 二进制序列类型 —-
bytes
,bytearray
,memoryview
- 集合类型 —-
set
,frozenset
- 映射类型 —-
dict
- 上下文管理器类型
- Type Annotation Types —- Generic Alias, Union
- 其他内置类型
- 特殊属性
内置异常
- 基类
- 具体异常
- 警告
- 异常层次结构
文本处理服务
string
—- 常见的字符串操作re
—- 正则表达式操作difflib
—- 计算差异的辅助工具textwrap
—- 文本自动换行与填充unicodedata
—- Unicode 数据库stringprep
—- 因特网字符串预备readline
—- GNU readline 接口rlcompleter
—- GNU readline 的补全函数
二进制数据服务
struct
—- 将字节串解读为打包的二进制数据codecs
—- 编解码器注册和相关基类
数据类型
datetime
—- 基本日期和时间类型zoneinfo
—- IANA 时区支持calendar
—- 日历相关函数collections
—- 容器数据类型collections.abc
—- 容器的抽象基类heapq
—- 堆队列算法bisect
—- 数组二分查找算法array
—- 高效的数值数组weakref
—- 弱引用types
—- 动态类型创建和内置类型名称copy
—- 浅层 (shallow) 和深层 (deep) 复制操作pprint
—- 数据美化输出reprlib
—- 另一种repr()
实现enum
—- 对枚举的支持graphlib
—- 操作类似图的结构的功能
数字和数学模块
numbers
—- 数字的抽象基类math
—- 数学函数cmath
—- 关于复数的数学函数decimal
—- 十进制定点和浮点运算fractions
—- 分数random
—- 生成伪随机数statistics
—- 数学统计函数
概述
“Python 库”中包含了几种不同的组件。
它包含通常被视为语言“核心”中的一部分的数据类型,例如数字和列表。对于这些类型,Python语言核心定义了文字的形式,并对它们的语义设置了一些约束,但没有完全定义语义。(另一方面,语言核心确实定义了语法属性,如操作符的拼写和优先级。)
这个库也包含了内置函数和异常 —- 不需要 import
语句就可以在所有Python代码中使用的对象。有一些是由语言核心定义的,但是许多对于核心语义不是必需的,并且仅在这里描述。
不过这个库主要是由一系列的模块组成。这些模块集可以不同方式分类。有些模块是用 C 编写并内置于 Python 解释器中;另一些模块则是用 Python 编写并以源码形式导入。有些模块提供专用于 Python 的接口,例如打印栈追踪信息;有些模块提供专用于特定操作系统的接口,例如操作特定的硬件;另一些模块则提供针对特定应用领域的接口,例如万维网。有些模块在所有更新和移植版本的 Python 中可用;另一些模块仅在底层系统支持或要求时可用;还有些模块则仅当编译和安装 Python 时选择了特定配置选项时才可用。
内置函数
Python 解释器内置了很多函数和类型,任何时候都能使用。以下按字母顺序给出列表。
abs
(x)
返回一个数的绝对值。 参数可以是整数、浮点数或任何实现了 __abs__()
的对象。 如果参数是一个复数,则返回它的模。
aiter
(async_iterable)
返回 asynchronous iterable 的 asynchronous iterator 。相当于调用 x.__aiter__()
。
aiter(x)
本身带有__aiter__()
方法,返回x
,所以aiter(aiter(x))
与aiter(x)
相同。
注意:与 iter()
不同,aiter()
没有两个参数的版本。
3.10 新版功能.
all
(iterable)
如果 iterable 的所有元素均为真值(或可迭代对象为空)则返回 True
。 等价于:
def all(iterable):
for element in iterable:
if not element:
return False
return True
- awaitable
anext
(async_iterator[, default])
当进入 await 状态时,从给定 asynchronous iterator 返回下一数据项,迭代完毕则返回 default。
这是内置函数 next()
的异步版本,类似于:
调用 async_iterator 的 __anext__()
方法,返回一个 awaitable。等待返回迭代器的下一个值。若有给出 default,则在迭代完毕后会返回给出的值,否则会触发 StopAsyncIteration
。
3.10 新版功能.
any
(iterable)
如果 iterable 的任一元素为真值则返回 True
。 如果可迭代对象为空,返回 False
。 等价于:
def any(iterable):
for element in iterable:
if element:
return True
return False
ascii
(object)
与 repr()
类似,返回一个字符串,表示对象的可打印形式,但在 repr()
返回的字符串中,非 ASCII 字符会用 \x
、\u
和 \U
进行转义。生成的字符串类似于 Python 2 中 repr()
的返回结果。
bin
(x)
将整数转变为以“0b”前缀的二进制字符串。结果是一个合法的 Python 表达式。如果 x 不是 Python 的 int
对象,它必须定义 __index__()
方法,以便返回整数值。下面是一些例子:
>>> bin(3)
'0b11'
>>> bin(-10)
'-0b1010'
若要控制是否显示前缀“0b”,可以采用以下两种方案:
>>> format(14,'#b'), format(14,'b')
('0b1110','1110')
>>> f'{14:#b}', f'{14:b}'
('0b1110','1110')
另见 format()
获取更多信息。
- class
bool
([x])
返回布尔值,True
或 False
。x 用标准的 真值测试过程 进行转换。如果 x 为 False 或省略,则返回 False
;否则返回 True
。 bool
类是 int
的子类。它不能再被继承。它唯一的实例就是 False
和 True
。
在 3.7 版更改: x 现在只能作为位置参数。
breakpoint
(\args, *kws)
此函数会在调用时将你陷入调试器中。具体来说,它调用 sys.breakpointhook()
,直接传递 args
和 kws
。默认情况下, sys.breakpointhook()
调用 pdb.set_trace()
且没有参数。在这种情况下,它纯粹是一个便利函数,因此您不必显式导入 pdb
且键入尽可能少的代码即可进入调试器。但是, sys.breakpointhook()
可以设置为其他一些函数并被 breakpoint()
自动调用,以允许进入你想用的调试器。
引发一个 审计事件builtins.breakpoint
并附带参数 breakpointhook
。
3.7 新版功能.
- class
bytearray
([source[, encoding[, errors]]])
返回一个新的 bytes 数组。 bytearray
类是一个可变序列,包含范围为 0 <= x < 256 的整数。它有可变序列大部分常见的方法,见 可变序列类型 的描述;同时有 bytes
类型的大部分方法。
可选形参 source 可以用不同的方式来初始化数组:
- 如果是一个 string*,您必须提供 *encoding 参数(errors 参数仍是可选的);
bytearray()
会使用str.encode()
方法来将 string 转变成 bytes。 - 如果是一个 integer,会初始化大小为该数字的数组,并使用 null 字节填充。
- 如果是一个遵循 缓冲区接口 的对象,该对象的只读缓冲区将被用来初始化字节数组。
- 如果是一个 iterable 可迭代对象,它的元素的范围必须是
0 <= x < 256
的整数,它会被用作数组的初始内容。
如果没有实参,则创建大小为 0 的数组。
- class
bytes
([source[, encoding[, errors]]])
返回一个新的“bytes”对象,这是一个不可变序列,包含范围为 0 <= x < 256
的整数。bytes
是 bytearray
的不可变版本——带有同样不改变序列的方法,支持同样的索引、切片操作。
因此,构造函数的实参和 bytearray()
相同。
callable
(object)
如果参数 object 是可调用的就返回 True
,否则返回 False
。 如果返回 True
,调用仍可能失败,但如果返回 False
,则调用 object 将肯定不会成功。 请注意类是可调用的(调用类将返回一个新的实例);如果实例所属的类有 __call__()
则它就是可调用的。
3.2 新版功能: 这个函数一开始在 Python 3.0 被移除了,但在 Python 3.2 被重新加入。
chr
(i)
返回 Unicode 码位为整数 i 的字符的字符串格式。例如,chr(97)
返回字符串 'a'
,chr(8364)
返回字符串 '€'
。这是 ord()
的逆函数。
实参的合法范围是 0 到 1,114,111(16 进制表示是 0x10FFFF)。如果 i 超过这个范围,会触发 ValueError
异常。
@classmethod
把一个方法封装成类方法。
类方法隐含的第一个参数就是类,就像实例方法接收实例作为参数一样。要声明一个类方法,按惯例请使用以下方案:
class C:
@classmethod
def f(cls, arg1, arg2,...):...
@classmethod
这样的形式称为函数的 decorator 。
类方法的调用可以在类上进行 (例如 C.f()
) 也可以在实例上进行 (例如 C().f()
)。 其所属类以外的类实例会被忽略。 如果类方法在其所属类的派生类上调用,则该派生类对象会被作为隐含的第一个参数被传入。
类方法与 C++ 或 Java 中的静态方法不同。
在 3.9 版更改: 类方法现在可以包装其他 描述器 例如 property()
。
在 3.10 版更改: 类方法现在继承了方法的属性(__module__
、__name__
、__qualname__
、__doc__
和 __annotations__
),并拥有一个新的__wrapped__
属性。
compile
(source, filename, mode, flags=0, dont_inherit=False, optimize=- 1)
将 source 编译成代码或 AST 对象。代码对象可以被 exec()
或 eval()
执行。source 可以是常规的字符串、字节字符串,或者 AST 对象。
filename 实参需要是代码读取的文件名;如果代码不需要从文件中读取,可以传入一些可辨识的值(经常会使用 '<string>'
)。
mode 实参指定了编译代码必须用的模式。如果 source 是语句序列,可以是 'exec'
;如果是单一表达式,可以是 'eval'
;如果是单个交互式语句,可以是 'single'
。(在最后一种情况下,如果表达式执行结果不是 None
将会被打印出来。)
可选参数 flags 和 dont_inherit 控制应当激活哪个 编译器选项 以及应当允许哪个 future 特性。 如果两者都未提供 (或都为零) 则代码会应用与调用 compile()
的代码相同的旗标来编译。 如果给出了 flags 参数而未给出 dont_inherit (或者为零) 则会在无论如何都将被使用的旗标之外还会额外使用 flags 参数所指定的编译器选项和 future 语句。 如果 dont_inherit 为非零整数,则只使用 flags 参数 — 外围代码中的旗标 (future 特性和编译器选项) 会被忽略。
编译器选项和 future 语句是由比特位来指明的。 比特位可以通过一起按位 OR 来指明多个选项。 指明特定 future 特性所需的比特位可以在 __future__
模块的 _Feature
实例的 compiler_flag
属性中找到。 编译器旗标 可以在 ast
模块中查找带有 PyCF_
前缀的名称。
optimize 实参指定编译器的优化级别;默认值 -1
选择与解释器的 -O
选项相同的优化级别。显式级别为 0
(没有优化;__debug__
为真)、1
(断言被删除, __debug__
为假)或 2
(文档字符串也被删除)。
如果编译的源码不合法,此函数会触发 SyntaxError
异常;如果源码包含 null 字节,则会触发 ValueError
异常。
引发一个 审计事件compile
附带参数 source
, filename
。
注解
在 'single'
或 'eval'
模式编译多行代码字符串时,输入必须以至少一个换行符结尾。 这使 code
模块更容易检测语句的完整性。
警告
在将足够大或者足够复杂的字符串编译成 AST 对象时,Python 解释器有可能因为 Python AST 编译器的栈深度限制而崩溃。
在 3.2 版更改: Windows 和 Mac 的换行符均可使用。而且在 'exec'
模式下的输入不必再以换行符结尾了。另增加了 optimize 参数。
在 3.5 版更改: 之前 source 中包含 null 字节的话会触发 TypeError
异常。
3.8 新版功能: ast.PyCF_ALLOW_TOP_LEVEL_AWAIT
现在可在旗标中传入以启用对最高层级 await
, async for
和 async with
的支持。
- class
complex
([real[, imag]])
返回值为 real + imagj 的复数,或将字符串或数字转换为复数。如果第一个形参是字符串,则它被解释为一个复数,并且函数调用时必须没有第二个形参。第二个形参不能是字符串。每个实参都可以是任意的数值类型(包括复数)。如果省略了 imag,则默认值为零,构造函数会像 int
和 float
一样进行数值转换。如果两个实参都省略,则返回 0j
。
对于一个普通 Python 对象 x
,complex(x)
会委托给 x.__complex__()
。 如果 __complex__()
未定义则将回退至 __float__()
。 如果 __float__()
未定义则将回退至 __index__()
。
注解
当从字符串转换时,字符串在 +
或 -
的周围必须不能有空格。例如 complex('1+2j')
是合法的,但 complex('1 + 2j')
会触发 ValueError
异常。
在 3.6 版更改: 您可以使用下划线将代码文字中的数字进行分组。
在 3.8 版更改: 如果 __complex__()
和 __float__()
未定义则回退至 __index__()
。
delattr
(object, name)
setattr()
相关的函数。实参是一个对象和一个字符串。该字符串必须是对象的某个属性。如果对象允许,该函数将删除指定的属性。例如 delattr(x, 'foobar')
等价于 del x.foobar
。
- class
dict
(**kwarg)* - class
dict
(*mapping, **kwarg)
- class
dict
(*iterable, **kwarg)
创建一个新的字典。dict
对象是一个字典类。
dir
([object])
如果没有实参,则返回当前本地作用域中的名称列表。如果有实参,它会尝试返回该对象的有效属性列表。
如果对象有一个名为 __dir__()
的方法,那么该方法将被调用,并且必须返回一个属性列表。这允许实现自定义 __getattr__()
或 __getattribute__()
函数的对象能够自定义 dir()
来报告它们的属性。
如果对象未提供 __dir__()
方法,该函数会尽量从对象的 __dict__
属性和其类型对象中收集信息。得到的列表不一定是完整,如果对象带有自定义 __getattr__()
方法时,结果可能不准确。
默认的 dir()
机制对不同类型的对象行为不同,它会试图返回最相关而不是最全的信息:
- 如果对象是模块对象,则列表包含模块的属性名称。
- 如果对象是类型或类对象,则列表包含它们的属性名称,并且递归查找所有基类的属性。
- 否则,列表包含对象的属性名称,它的类属性名称,并且递归查找它的类的所有基类的属性。
返回的列表按字母表排序。例如:
>>>import struct
>>> dir()# show the names in the module namespace
['__builtins__','__name__','struct']
>>> dir(struct)# show the names in the struct module
['Struct','__all__','__builtins__','__cached__','__doc__','__file__',
'__initializing__','__loader__','__name__','__package__',
'_clearcache','calcsize','error','pack','pack_into',
'unpack','unpack_from']
>>>class Shape:
...def __dir__(self):
...return['area','perimeter','location']
>>> s =Shape()
>>> dir(s)
['area','location','perimeter']
注解
因为 dir()
主要是为了便于在交互式时使用,所以它会试图返回人们感兴趣的名字集合,而不是试图保证结果的严格性或一致性,它具体的行为也可能在不同版本之间改变。例如,当实参是一个类时,metaclass 的属性不包含在结果列表中。
divmod
(a, b)
以两个(非复数)数字为参数,在作整数除法时,返回商和余数。若操作数为混合类型,则适用二进制算术运算符的规则。对于整数而言,结果与 (a // b, a % b)
相同。对于浮点数则结果为(q, a % b)
,其中 q 通常为 math.floor(a / b)
,但可能比它小 1。在任何情况下,q * b + a % b
都非常接近 a,如果 a % b
非零,则结果符号与 b 相同,并且 0 <= abs(a % b) < abs(b)
。
enumerate
(iterable, start=0)
返回一个枚举对象。iterable 必须是一个序列,或 iterator,或其他支持迭代的对象。 enumerate()
返回的迭代器的 __next__()
方法返回一个元组,里面包含一个计数值(从 start 开始,默认为 0)和通过迭代 iterable 获得的值。
>>> seasons =['Spring','Summer','Fall','Winter']
>>> list(enumerate(seasons))
[(0,'Spring'),(1,'Summer'),(2,'Fall'),(3,'Winter')]
>>> list(enumerate(seasons, start=1))
[(1,'Spring'),(2,'Summer'),(3,'Fall'),(4,'Winter')]
等价于:
def enumerate(sequence, start=0):
n = start
for elem in sequence:
yield n, elem
n +=1
eval
(expression[, globals[, locals]])
实参是一个字符串,以及可选的 globals 和 locals。globals 实参必须是一个字典。locals 可以是任何映射对象。
表达式解析参数 expression 并作为 Python 表达式进行求值(从技术上说是一个条件列表),采用 globals 和 locals 字典作为全局和局部命名空间。 如果存在 globals 字典,并且不包含 __builtins__
键的值,则在解析 expression 之前会插入以该字符串为键以对内置模块 builtins
的字典的引用为值的项。 这样就可以在将 globals 传给 eval()
之前通过向其传入你自己的 __builtins__
字典来控制可供被执行代码可以使用哪些内置模块。 如果 locals 字典被省略则它默认为 globals 字典。 如果两个字典都被省略,则将使用调用 eval()
的环境中的 globals 和 locals 来执行该表达式。 注意,eval() 无法访问闭包环境中的 嵌套作用域 (非局部变量)。
返回值就是表达式的求值结果。 语法错误将作为异常被报告。 例如:
>>> x =1
>>>eval('x+1')
2
该函数还可用于执行任意代码对象(比如由 compile()
创建的对象)。 这时传入的是代码对象,而非一个字符串了。如果代码对象已用参数为 mode 的 'exec'
进行了编译,那么 eval()
的返回值将为 None
。
提示: exec()
函数支持语句的动态执行。 globals()
和 locals()
函数分别返回当前的全局和本地字典,可供传给 eval()
或 exec()
使用。
如果给出的源数据是个字符串,那么其前后的空格和制表符将被剔除。
引发一个 审计事件exec
附带参数 code_object
。
exec
(object[, globals[, locals]])
这个函数支持动态执行 Python 代码。 object 必须是字符串或者代码对象。 如果是字符串,那么该字符串将被解析为一系列 Python 语句并执行(除非发生语法错误)。 如果是代码对象,它将被直接执行。 在任何情况下,被执行的代码都应当是有效的文件输入(见参考手册中的“文件输入”一节)。 请注意即使在传递给 exec()
函数的代码的上下文中,nonlocal
, yield
和 return
语句也不能在函数定义以外使用。 该函数的返回值是 None
。
无论在什么情况下,如果省略了可选部分,代码将运行于当前作用域中。如果只提供了 globals*,则必须为字典对象(而不能是字典的子类),同时用于存放全局变量和局部变量。如果提供了 *globals 和 locals,则将分别用于全局变量和局部变量。locals 可以是任意字典映射对象。请记住,在模块级别,globals 和 locals 是同一个字典。如果 exec 获得两个独立的对象作为 globals 和 locals,代码执行起来就像嵌入到某个类定义中一样。
如果 globals 字典不包含 __builtins__
键值,则将为该键插入对内建 builtins
模块字典的引用。因此,在将执行的代码传递给 exec()
之前,可以通过将自己的 __builtins__
字典插入到 globals 中来控制可以使用哪些内置代码。
引发一个 审计事件exec
附带参数 code_object
。
注解
内置 globals()
和 locals()
函数各自返回当前的全局和本地字典,因此可以将它们传递给 exec()
的第二个和第三个实参。
注解
默认情况下,locals 的行为如下面 locals()
函数描述的一样:不要试图改变默认的 locals 字典。如果您想在 exec()
函数返回时知道代码对 locals 的变动,请明确地传递 locals 字典。
filter
(function, iterable)
用 iterable 中函数 function 返回真的那些元素,构建一个新的迭代器。iterable 可以是一个序列,一个支持迭代的容器,或一个迭代器。如果 function 是 None
,则会假设它是一个身份函数,即 iterable 中所有返回假的元素会被移除。
请注意, filter(function, iterable)
相当于一个生成器表达式,当 function 不是 None
的时候为 (item for item in iterable if function(item))
;function 是 None
的时候为 (item for item in iterable if item)
。
请参阅 itertools.filterfalse()
了解,只有 function 返回 false 时才选取 iterable 中元素的补充函数。
- class
float
([x])
返回从数字或字符串 x 生成的浮点数。
如果参数是个字符串,则应包含一个十进制数字,前面可选带上符号,也可选前后带有空白符。符号可以是‘+’
或 '-'
;'+'
符号对值没有影响。参数也可以是一个代表 NaN(非数字)或正负无穷大的字符串。更确切地说,在去除前导和尾部的空白符后,输入参数必须符合以下语法:
sign ::="+"|"-"
infinity ::="Infinity"|"inf"
nan ::="nan"
numeric_value ::=floatnumber|infinity|nan
numeric_string::=[sign]numeric_value
这里的 floatnumber
是指 Python 的浮点数格式,在 浮点数字面值 中有介绍。大小写没有关系,所以“inf”、“Inf”、“INFINITY”、“iNfINity”都可接受为正无穷的拼写形式。
另一方面,如果实参是整数或浮点数,则返回具有相同值(在 Python 浮点精度范围内)的浮点数。如果实参在 Python 浮点精度范围外,则会触发 OverflowError
。
对于一个普通 Python 对象 x
,float(x)
会委托给 x.__float__()
。 如果 __float__()
未定义则将回退至 __index__()
。
如果没有实参,则返回 0.0
。
示例:
>>>float('+1.23')
1.23
>>>float(' -12345\n')
-12345.0
>>>float('1e-003')
0.001
>>>float('+1E6')
1000000.0
>>>float('-Infinity')
-inf
在 3.6 版更改: 您可以使用下划线将代码文字中的数字进行分组。
在 3.7 版更改: x 现在只能作为位置参数。
在 3.8 版更改: 如果 __float__()
未定义则回退至 __index__()
。
format
(value[, format_spec])
将 value 转换为“格式化后”的形式,格式由 format_spec 进行控制。format_spec 的解释方式取决于 value 参数的类型;但大多数内置类型使用一种标准的格式化语法: 格式规格迷你语言。
默认的 format_spec 是一个空字符串,它通常给出与调用 str(value)
相同的结果。
调用 format(value, format_spec)
会转换成 type(value).__format__(value, format_spec)
,所以实例字典中的 __format__()
方法将不会调用。如果方法搜索回退到 object
类但 format_spec 不为空,或者如果 format_spec 或返回值不是字符串,则会触发 TypeError
异常。
在 3.4 版更改: 当 format_spec 不是空字符串时, object().__format__(format_spec)
会触发 TypeError
。
- class
frozenset
([iterable])
返回一个新的 frozenset
对象,它包含可选参数 iterable 中的元素。 frozenset
是一个内置的类。
getattr
(object, name[, default])
返回对象命名属性的值。name 必须是字符串。如果该字符串是对象的属性之一,则返回该属性的值。例如, getattr(x, 'foobar')
等同于 x.foobar
。如果指定的属性不存在,且提供了 default 值,则返回它,否则触发 AttributeError
。
注解
由于 私有名称混合 发生在编译时,因此必须 手动混合私有属性(以两个下划线打头的属性)名称以使使用 getattr()
来提取它。
globals
()
返回表示当前全局符号表的字典。这总是当前模块的字典(在函数或方法中,不是调用它的模块,而是定义它的模块)。
hasattr
(object, name)
该实参是一个对象和一个字符串。如果字符串是对象的属性之一的名称,则返回 True
,否则返回 False
。(此功能是通过调用 getattr(object, name)
看是否有 AttributeError
异常来实现的。)
hash
(object)
返回该对象的哈希值(如果它有的话)。哈希值是整数。它们在字典查找元素时用来快速比较字典的键。相同大小的数字变量有相同的哈希值(即使它们类型不同,如 1 和 1.0)。
注解
如果对象实现了自己的 __hash__()
方法,请注意,hash()
根据机器的字长来截断返回值。
help
([object])
启动内置的帮助系统(此函数主要在交互式中使用)。如果没有实参,解释器控制台里会启动交互式帮助系统。如果实参是一个字符串,则在模块、函数、类、方法、关键字或文档主题中搜索该字符串,并在控制台上打印帮助信息。如果实参是其他任意对象,则会生成该对象的帮助页。
请注意,如果在调用 help()
时,目标函数的形参列表中存在斜杠(/),则意味着斜杠之前的参数只能是位置参数。
该函数通过 site
模块加入到内置命名空间。
在 3.4 版更改: pydoc
和 inspect
的变更使得可调用对象的签名信息更加全面和一致。
hex
(x)
将整数转换为以“0x”为前缀的小写十六进制字符串。如果 x 不是 Python int
对象,则必须定义返回整数的 __index__()
方法。一些例子:
>>> hex(255)
'0xff'
>>> hex(-42)
'-0x2a'
如果要将整数转换为大写或小写的十六进制字符串,并可选择有无“0x”前缀,则可以使用如下方法:
>>>'%#x'%255,'%x'%255,'%X'%255
('0xff','ff','FF')
>>> format(255,'#x'), format(255,'x'), format(255,'X')
('0xff','ff','FF')
>>> f'{255:#x}', f'{255:x}', f'{255:X}'
('0xff','ff','FF')
注解
如果要获取浮点数的十六进制字符串形式,请使用 float.hex()
方法。
id
(object)
返回对象的“标识值”。该值是一个整数,在此对象的生命周期中保证是唯一且恒定的。两个生命期不重叠的对象可能具有相同的 id()
值。
CPython implementation detail: This is the address of the object in memory.
引发一个 审计事件builtins.id
,附带参数 id
。
input
([prompt])
如果存在 prompt 实参,则将其写入标准输出,末尾不带换行符。接下来,该函数从输入中读取一行,将其转换为字符串(除了末尾的换行符)并返回。当读取到 EOF 时,则触发 EOFError
。例如:
>>> s = input('--> ')
-->MontyPython's Flying Circus
>>> s
"Monty Python's FlyingCircus"
如果加载了 readline
模块,input()
将使用它来提供复杂的行编辑和历史记录功能。
引发一个 审计事件builtins.input
附带参数 prompt
。
在成功读取输入之后引发一个审计事件 builtins.input/result
附带结果。
class
int
([x])class
int
(x, base=10)
返回一个基于数字或字符串 x 构造的整数对象,或者在未给出参数时返回 0
。 如果 x 定义了 __int__()
,int(x)
将返回 x.__int__()
。 如果 x 定义了 __index__()
,它将返回 x.__index__()
。 如果 x 定义了 __trunc__()
,它将返回 x.__trunc__()
。 对于浮点数,它将向零舍入。
如果 x 不是数字,或者有 base 参数,x 必须是字符串、bytes
、表示进制为 base 的 整数字面值 的 bytearray
实例。该文字前可以有 +
或 -
(中间不能有空格),前后可以有空格。一个进制为 n 的数字包含 0 到 n-1 的数,其中 a
到 z
(或 A
到 Z
)表示 10 到 35。默认的 base 为 10 ,允许的进制有 0、2-36。2、8、16 进制的数字可以在代码中用 0b
/0B
、 0o
/0O
、 0x
/0X
前缀来表示。进制为 0 将安照代码的字面量来精确解释,最后的结果会是 2、8、10、16 进制中的一个。所以 int('010', 0)
是非法的,但 int('010')
和 int('010', 8)
是合法的。
在 3.4 版更改: 如果 base 不是 int
的实例,但 base 对象有 base.__index__
方法,则会调用该方法来获取进制数。以前的版本使用 base.__int__
而不是 base.__index__
。
在 3.6 版更改: 您可以使用下划线将代码文字中的数字进行分组。
在 3.7 版更改: x 现在只能作为位置参数。
在 3.8 版更改: 如果 __int__()
未定义则回退至 __index__()
。
isinstance
(object, classinfo)
如果 object 参数是 classinfo 参数的实例,或其(直接、间接或 virtual )子类的实例,则返回 True
。 如果 object 不是给定类型的对象,则总是返回 False
。如果 classinfo 是类型对象的元组(或由该类元组递归生成)或多个类型的 Union Type,那么当 object 是其中任一类型的实例时就会返回 True
。如果 classinfo 不是某个类型或类型元组,将会触发 TypeError
异常。
在 3.10 版更改: classinfo 可以是一个 Union Type。
issubclass
(class, classinfo)
Return True
if class is a subclass (direct, indirect, or virtual) of classinfo. A class is considered a subclass of itself. classinfo may be a tuple of class objects or a Union Type, in which case return True
if class is a subclass of any entry in classinfo. In any other case, a TypeError
exception is raised.
在 3.10 版更改: classinfo 可以是一个 Union Type。
iter
(object[, sentinel])
返回一个 iterator 对象。根据是否存在第二个实参,第一个实参的解释是非常不同的。如果没有第二个实参,object 必须是支持迭代协议(有 __iter__()
方法)的集合对象,或必须支持序列协议(有 __getitem__()
方法,且数字参数从 0
开始)。如果它不支持这些协议,会触发 TypeError
。如果有第二个实参 sentinel*,那么 *object 必须是可调用的对象。这种情况下生成的迭代器,每次迭代调用它的 __next__()
方法时都会不带实参地调用 object*;如果返回的结果是 *sentinel 则触发 StopIteration
,否则返回调用结果。
适合 iter()
的第二种形式的应用之一是构建块读取器。 例如,从二进制数据库文件中读取固定宽度的块,直至到达文件的末尾:
from functools importpartial
with open('mydata.db','rb')as f:
for block in iter(partial(f.read,64), b''):
process_block(block)
len
(s)
返回对象的长度(元素个数)。实参可以是序列(如 string、bytes、tuple、list 或 range 等)或集合(如 dictionary、set 或 frozen set 等)。
CPython implementation detail:len
对于大于 sys.maxsize
的长度如 range(2 ** 100)
会引发 OverflowError
。
- class
list
([iterable])
虽然被称为函数,list
实际上是一种可变序列类型。
locals
()
更新并返回表示当前本地符号表的字典。 在函数代码块但不是类代码块中调用 locals()
时将返回自由变量。 请注意在模块层级上,locals()
和 globals()
是同一个字典。
注解
不要更改此字典的内容;更改不会影响解释器使用的局部变量或自由变量的值。
map
(function, iterable, …)
返回一个将 function 应用于 iterable 中每一项并输出其结果的迭代器。 如果传入了额外的 iterable 参数,function 必须接受相同个数的实参并被应用于从所有可迭代对象中并行获取的项。 当有多个可迭代对象时,最短的可迭代对象耗尽则整个迭代就将结束。 对于函数的输入已经是参数元组的情况。
max
(iterable, **[, key, default*])max
(arg1, arg2, \args[, key*])
返回可迭代对象中最大的元素,或者返回两个及以上实参中最大的。
如果只提供了一个位置参数,它必须是非空 iterable,返回可迭代对象中最大的元素;如果提供了两个及以上的位置参数,则返回最大的位置参数。
有两个可选只能用关键字的实参。key 实参指定排序函数用的参数,如传给 list.sort()
的。default 实参是当可迭代对象为空时返回的值。如果可迭代对象为空,并且没有给 default ,则会触发 ValueError
。
如果有多个最大元素,则此函数将返回第一个找到的。这和其他稳定排序工具如 sorted(iterable, key=keyfunc, reverse=True)[0]
和 heapq.nlargest(1, iterable, key=keyfunc)
保持一致。
3.4 新版功能: keyword-only 实参 default 。
在 3.8 版更改: key 可以为 None
。
- class
memoryview
(object)
返回由给定实参创建的“内存视图”对象。
min
(iterable, **[, key, default*])min
(arg1, arg2, \args[, key*])
返回可迭代对象中最小的元素,或者返回两个及以上实参中最小的。
如果只提供了一个位置参数,它必须是 iterable,返回可迭代对象中最小的元素;如果提供了两个及以上的位置参数,则返回最小的位置参数。
有两个可选只能用关键字的实参。key 实参指定排序函数用的参数,如传给 list.sort()
的。default 实参是当可迭代对象为空时返回的值。如果可迭代对象为空,并且没有给 default ,则会触发 ValueError
。
如果有多个最小元素,则此函数将返回第一个找到的。这和其他稳定排序工具如 sorted(iterable, key=keyfunc)[0]
和 heapq.nsmallest(1, iterable, key=keyfunc)
保持一致。
3.4 新版功能: keyword-only 实参 default 。
在 3.8 版更改: key 可以为 None
。
next
(iterator[, default])
通过调用 iterator 的 __next__()
方法获取下一个元素。如果迭代器耗尽,则返回给定的 default,如果没有默认值则触发 StopIteration
。
- class
object
返回一个不带特征的新对象。object
是所有类的基类。它带有所有 Python 类实例均通用的方法。本函数不接受任何参数。
注解
由于 object
没有 __dict__
,因此无法将任意属性赋给 object
的实例。
oct
(x)
将一个整数转变为一个前缀为“0o”的八进制字符串。结果是一个合法的 Python 表达式。如果 x 不是 Python 的 int
对象,那它需要定义 __index__()
方法返回一个整数。一些例子:
>>> oct(8)
'0o10'
>>> oct(-56)
'-0o70'
若要将整数转换为八进制字符串,并可选择是否带有“0o”前缀,可采用如下方法:
>>>'%#o'%10,'%o'%10
('0o12','12')
>>> format(10,'#o'), format(10,'o')
('0o12','12')
>>> f'{10:#o}', f'{10:o}'
('0o12','12')
open
(file, mode=’r’, buffering=- 1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
打开 file 并返回对应的 file object。 如果该文件不能被打开,则引发 OSError
。
file 是一个 path-like object,表示将要打开的文件的路径(绝对路径或者相对当前工作目录的路径),也可以是要封装文件对应的整数类型文件描述符。(如果给出的是文件描述符,则当返回的 I/O 对象关闭时它也会关闭,除非将 closefd 设为 False
。)
mode 是可选的字符串,用于指定打开文件的模式。默认值是 'r'
,表示以文本模式打开并读取文件。其他常见模式有:写入模式 'w'
(已存在文件会被清空)、独占创建模式 'x'
、追加写入模式 'a'
(在 某些 Unix 系统中,无论当前文件指针在什么位置,所有 的写入操作都会追加到文件末尾)。在文本模式,如果未指定 encoding ,则会根据当前平台决定编码格式:调用 locale.getpreferredencoding(False)
获取当前地区的编码。若要读写原生字节格式,请使用二进制模式且不要指定 encoding。可用的模式有:
字符 | 含意 |
---|---|
‘r’ |
读取(默认) |
‘w’ |
写入,并先截断文件 |
‘x’ |
排它性创建,如果文件已存在则失败 |
‘a’ |
打开文件用于写入,如果文件存在则在末尾追加 |
‘b’ |
二进制模式 |
‘t’ |
文本模式(默认) |
‘+’ |
打开用于更新(读取与写入) |
默认模式为 'r'
(打开文件用于读取文本,与 'rt'
同义)。'w+'
和 'w+b'
模式将打开文件并清空内容。而 'r+'
和 'r+b'
模式将打开文件但不清空内容。
正如在 概述 中提到的,Python区分二进制和文本I/O。以二进制模式打开的文件(包括 mode 参数中的 'b'
)返回的内容为 bytes
对象,不进行任何解码。在文本模式下(默认情况下,或者在 mode 参数中包含 't'
)时,文件内容返回为 str
,首先使用指定的 encoding (如果给定)或者使用平台默认的的字节编码解码。
另外还有一种模式字符 'U'
可用,不过它已失效,并视作弃用。以前它会在文本模式中启用 universal newlines,这在 Python 3.0 已成为默认行为。详情请参阅 newline 形参的文档。
注解
Python不依赖于底层操作系统的文本文件概念;所有处理都由Python本身完成,因此与平台无关。
buffering 是一个可选的整数,用于设置缓冲策略。传递0以切换缓冲关闭(仅允许在二进制模式下),1选择行缓冲(仅在文本模式下可用),并且>1的整数以指示固定大小的块缓冲区的大小(以字节为单位)。如果没有给出 buffering 参数,则默认缓冲策略的工作方式如下:
- 二进制文件以固定大小的块进行缓冲;使用启发式方法选择缓冲区的大小,尝试确定底层设备的“块大小”或使用
io.DEFAULT_BUFFER_SIZE
。在许多系统上,缓冲区的长度通常为4096或8192字节。 - “交互式”文本文件(
isatty()
返回True
的文件)使用行缓冲。其他文本文件使用上述策略用于二进制文件。
encoding 是用于解码或编码文件的编码的名称。这应该只在文本模式下使用。默认编码是依赖于平台的(不 管 locale.getpreferredencoding()
返回何值),但可以使用任何Python支持的 text encoding 。有关支持的编码列表,请参阅 codecs
模块。
errors 是一个可选的字符串参数,用于指定如何处理编码和解码错误 - 这不能在二进制模式下使用。可以使用各种标准错误处理程序,但是使用 codecs.register_error()
注册的任何错误处理名称也是有效的。标准名称包括:
- 如果存在编码错误,
'strict'
会引发ValueError
异常。 默认值None
具有相同的效果。 'ignore'
忽略错误。请注意,忽略编码错误可能会导致数据丢失。'replace'
会将替换标记(例如'?'
)插入有错误数据的地方。'surrogateescape'
将把任何不正确的字节表示为 U+DC80 至 U+DCFF 范围内的下方替代码位。 当在写入数据时使用surrogateescape
错误处理句柄时这些替代码位会被转回到相同的字节。 这适用于处理具有未知编码格式的文件。- 只有在写入文件时才支持
'xmlcharrefreplace'
。编码不支持的字符将替换为相应的XML字符引用&#nnn;
。 'backslashreplace'
用Python的反向转义序列替换格式错误的数据。'namereplace'
(也只在编写时支持)用\N{...}
转义序列替换不支持的字符。
newline 控制 universal newlines 模式如何生效(它仅适用于文本模式)。它可以是 None
,''
,'\n'
,'\r'
和 '\r\n'
。它的工作原理:
- 从流中读取输入时,如果 newline 为
None
,则启用通用换行模式。输入中的行可以以'\n'
,'\r'
或'\r\n'
结尾,这些行被翻译成'\n'
在返回呼叫者之前。如果它是''
,则启用通用换行模式,但行结尾将返回给调用者未翻译。如果它具有任何其他合法值,则输入行仅由给定字符串终止,并且行结尾将返回给未调用的调用者。 - 将输出写入流时,如果 newline 为
None
,则写入的任何'\n'
字符都将转换为系统默认行分隔符os.linesep
。如果 newline 是''
或'\n'
,则不进行翻译。如果 newline 是任何其他合法值,则写入的任何'\n'
字符将被转换为给定的字符串。
如果 closefd 为 False
且给出的不是文件名而是文件描述符,那么当文件关闭时,底层文件描述符将保持打开状态。如果给出的是文件名,则 closefd 必须为 True
(默认值),否则将触发错误。
可以通过传递可调用的 opener 来使用自定义开启器。然后通过使用参数( file,flags )调用 opener 获得文件对象的基础文件描述符。 opener 必须返回一个打开的文件描述符(使用 os.open
as opener 时与传递 None
的效果相同)。
新创建的文件是 不可继承的。
下面的示例使用 os.open()
函数的 dir_fd 的形参,从给定的目录中用相对路径打开文件:
>>>import os
>>> dir_fd = os.open('somedir', os.O_RDONLY)
>>>def opener(path, flags):
...return os.open(path, flags, dir_fd=dir_fd)
...
>>>with open('spamspam.txt','w', opener=opener)as f:
...print('This will be written to somedir/spamspam.txt', file=f)
...
>>> os.close(dir_fd)# don't leak a file descriptor
open()
函数所返回的 file object 类型取决于所用模式。 当使用 open()
以文本模式 ('w'
, 'r'
, 'wt'
, 'rt'
等) 打开文件时,它将返回 io.TextIOBase
(特别是 io.TextIOWrapper
) 的一个子类。 当使用缓冲以二进制模式打开文件时,返回的类是 io.BufferedIOBase
的一个子类。 具体的类会有多种:在只读的二进制模式下,它将返回 io.BufferedReader
;在写入二进制和追加二进制模式下,它将返回 io.BufferedWriter
,而在读/写模式下,它将返回 io.BufferedRandom
。 当禁用缓冲时,则会返回原始流,即 io.RawIOBase
的一个子类 io.FileIO
。
引发一个 审计事件open
附带参数 file
, mode
, flags
。
mode
与 flags
参数可以在原始调用的基础上被修改或传递。
在 3.3 版更改:
- 增加了 opener 形参。
- 增加了
'x'
模式。- 过去触发的
IOError
,现在是OSError
的别名。- 如果文件已存在但使用了排它性创建模式(
'x'
),现在会触发FileExistsError
。在 3.4 版更改:
- 文件现在禁止继承。
Deprecated since version 3.4, removed in version 3.10: 'U'
模式。
在 3.5 版更改:
- 如果系统调用被中断,但信号处理程序没有触发异常,此函数现在会重试系统调用,而不是触发
InterruptedError
异常 (原因详见 PEP 475)。- 增加了
'namereplace'
错误处理接口。在 3.6 版更改:
- 增加对实现了
os.PathLike
对象的支持。- 在 Windows 上,打开一个控制台缓冲区将返回
io.RawIOBase
的子类,而不是io.FileIO
。
ord
(c)
对表示单个 Unicode 字符的字符串,返回代表它 Unicode 码点的整数。例如 ord('a')
返回整数 97
, ord('€')
(欧元符号)返回 8364
。这是 chr()
的逆函数。
pow
(base, exp[, mod])
返回 base 的 exp 次幂;如果 mod 存在,则返回 base 的 exp 次幂对 mod 取余(比 pow(base, exp) % mod
更高效)。 两参数形式 pow(base, exp)
等价于乘方运算符: base**exp
。
The arguments must have numeric types. With mixed operand types, the coercion rules for binary arithmetic operators apply. For int
operands, the result has the same type as the operands (after coercion) unless the second argument is negative; in that case, all arguments are converted to float and a float result is delivered. For example, pow(10, 2)
returns 100
, but pow(10, -2)
returns 0.01
.
对于 int
操作数 base 和 exp,如果给出 *mod,则 *mod 必须为整数类型并且 mod 必须不为零。 如果给出 mod 并且 exp 为负值,则 base 必须相对于 mod 不可整除。 在这种情况下,将会返回 pow(inv_base, -exp, mod)
,其中 inv_base 为 base 的倒数对 mod 取余。
下面的例子是 38
的倒数对 97
取余:
>>> pow(38,-1, mod=97)
23
>>>23*38%97==1
True
在 3.8 版更改: 对于 int
操作数,三参数形式的 pow
现在允许第二个参数为负值,即可以计算倒数的余数。
在 3.8 版更改: 允许关键字参数。 之前只支持位置参数。
print
(\objects, sep=’ ‘, end=’\n’, file=sys.stdout, flush=False*)
将 objects 打印输出至 file 指定的文本流,以 sep 分隔并在末尾加上 end*。 *sep 、 end 、 file 和 flush 必须以关键字参数的形式给出。
所有非关键字参数都会被转换为字符串,就像是执行了 str()
一样,并会被写入到流,以 sep 且在末尾加上 end*。 *sep 和 end 都必须为字符串;它们也可以为 None
,这意味着使用默认值。 如果没有给出 objects,则 print()
将只写入 end。
file 参数必须是一个具有 write(string)
方法的对象;如果参数不存在或为 None
,则将使用 sys.stdout
。 由于要打印的参数会被转换为文本字符串,因此 print()
不能用于二进制模式的文件对象。 对于这些对象,应改用 file.write(...)
。
输出是否缓存通常取决于 file*,但如果 *flush 关键字参数为 True,输出流会被强制刷新。
在 3.3 版更改: 增加了 flush 关键字参数。
- class
property
(fget=None, fset=None, fdel=None, doc=None)
返回 property 属性。
fget 是获取属性值的函数。 fset 是用于设置属性值的函数。 fdel 是用于删除属性值的函数。并且 doc 为属性对象创建文档字符串。
一个典型的用法是定义一个托管属性 x
:
class C:
def __init__(self):
self._x =None
def getx(self):
return self._x
def setx(self, value):
self._x = value
def delx(self):
delself._x
x =property(getx, setx, delx,"I'm the 'x' property.")
如果 c 为 C 的实例,c.x
将调用 getter,c.x = value
将调用 setter, del c.x
将调用 deleter。
如果给出,doc 将成为该 property 属性的文档字符串。 否则该 property 将拷贝 fget 的文档字符串(如果存在)。 这令使用 property()
作为 decorator 来创建只读的特征属性可以很容易地实现:
class Parrot:
def __init__(self):
self._voltage =100000
@property
def voltage(self):
"""Get the current voltage."""
return self._voltage
以上 @property
装饰器会将 voltage()
方法转化为一个具有相同名称的只读属性的 “getter”,并将 voltage 的文档字符串设置为 “Get the current voltage.”
特征属性对象具有 getter
, setter
以及 deleter
方法,它们可用作装饰器来创建该特征属性的副本,并将相应的访问函数设为所装饰的函数。 这最好是用一个例子来解释:
class C:
def __init__(self):
self._x =None
@property
def x(self):
"""I'm the 'x' property."""
return self._x
@x.setter
def x(self, value):
self._x = value
@x.deleter
def x(self):
delself._x
上述代码与第一个例子完全等价。 注意一定要给附加函数与原始的特征属性相同的名称 (在本例中为 x
。)
返回的特征属性对象同样具有与构造器参数相对应的属性 fget
, fset
和 fdel
。
在 3.5 版更改: 特征属性对象的文档字符串现在是可写的。
class
range
(stop)class
range
(start, stop[, step])
虽然被称为函数,但 range
实际上是一个不可变的序列类型。
repr
(object)
返回对象的可打印形式字符串。对于很多类型而言,本函数试图返回的字符串,会与将对象传给 eval()
所生成的结果相同;不然,结果就是一个尖括号包裹的字符串,包含了对象类型名称及其附加信息,附加信息通常包括对象的名称和内存地址。通过定义 __repr__()
方法,类可以控制本函数将为实例返回的内容。
reversed
(seq)
返回一个反向的 iterator。 seq 必须是一个具有 __reversed__()
方法的对象或者是支持该序列协议(具有从 0
开始的整数类型参数的 __len__()
方法和 __getitem__()
方法)。
round
(number[, ndigits])
返回 number 舍入到小数点后 ndigits 位精度的值。 如果 ndigits 被省略或为 None
,则返回最接近输入值的整数。
对于支持 round()
方法的内置类型,结果值会舍入至最接近的 10 的负 ndigits 次幂的倍数;如果与两个倍数同样接近,则选用偶数。因此,round(0.5)
和 round(-0.5)
均得出 0
而 round(1.5)
则为 2
。ndigits 可为任意整数值(正数、零或负数)。如果省略了 ndigits 或为 None
,则返回值将为整数。否则返回值与 number 的类型相同。
对于一般的 Python 对象 number
, round
将委托给 number.__round__
。
注解
对浮点数执行 round()
的行为可能会令人惊讶:例如,round(2.675, 2)
将给出 2.67
而不是期望的 2.68
。 这不算是程序错误:这一结果是由于大多数十进制小数实际上都不能以浮点数精确地表示。
- class
set
([iterable])
返回一个新的 set
对象,可以选择带有从 iterable 获取的元素。 set
是一个内置类型。
setattr
(object, name, value)
本函数与 getattr()
相对应。其参数为一个对象、一个字符串和一个任意值。字符串可以为某现有属性的名称,或为新属性。只要对象允许,函数会将值赋给属性。如 setattr(x, 'foobar', 123)
等价于 x.foobar = 123
。
注解
由于 私有名称混合 发生在编译时,因此必须手动混合私有属性(以两个下划线打头的属性)名称以便使用 setattr()
来设置它。
class
slice
(stop)class
slice
(start, stop[, step])
返回一个 slice 对象,代表由 range(start, stop, step)
指定索引集的切片。 其中参数 start 和 step 的默认值为 None
。切片对象具有只读数据属性 start
、stop
和 step
,只是返回对应的参数值(或默认值)。这几个属性没有其他明确的功能;不过 NumPy 和其他第三方扩展会用到。在使用扩展索引语法时,也会生成切片对象。例如: a[start:stop:step]
或 a[start:stop, i]
。 另一种方案是返回迭代器对象。
sorted
(iterable, **, key=None, reverse=False*)
根据 iterable 中的项返回一个新的已排序列表。
具有两个可选参数,它们都必须指定为关键字参数。
key 指定带有单个参数的函数,用于从 iterable 的每个元素中提取用于比较的键 (例如 key=str.lower
)。 默认值为 None
(直接比较元素)。
reverse 为一个布尔值。 如果设为 True
,则每个列表元素将按反向顺序比较进行排序。
使用 functools.cmp_to_key()
可将老式的 cmp 函数转换为 key 函数。
内置的 sorted()
确保是稳定的。 如果一个排序确保不会改变比较结果相等的元素的相对顺序就称其为稳定的 —- 这有利于进行多重排序(例如先按部门、再按薪级排序)。
The sort algorithm uses only <
comparisons between items. While defining an __lt__()
method will suffice for sorting, PEP 8 recommends that all six rich comparisons be implemented. This will help avoid bugs when using the same data with other ordering tools such as max()
that rely on a different underlying method. Implementing all six comparisons also helps avoid confusion for mixed type comparisons which can call reflected the __gt__()
method.
@staticmethod
将方法转换为静态方法。
静态方法不会接收隐式的第一个参数。要声明一个静态方法,请使用此语法
class C:
@staticmethod
def f(arg1, arg2,...):...
@staticmethod
这样的形式称为函数的 decorator 。
静态方法既可以由类中调用(如 C.f()
),也可以由实例中调用(如```C().f())。此外,还可以作为普通的函数进行调用(如
f()``)。
Python 的静态方法与 Java 或 C++ 类似。,可用于创建另一种类构造函数。
像所有装饰器一样,也可以像常规函数一样调用 staticmethod
,并对其结果执行某些操作。比如某些情况下需要从类主体引用函数并且您希望避免自动转换为实例方法。对于这些情况,请使用此语法:
def regular_function():
...
class C:
method = staticmethod(regular_function)
在 3.10 版更改: 静态方法继承了方法的多个属性(__module__
、__name__
、__qualname__
、__doc__
和 __annotations__
),还拥有一个新的__wrapped__
属性,并且现在还可以作为普通函数进行调用。
class
str
(object=’’)class
str
(object=b’’, encoding=’utf-8’, errors=’strict’)
返回一个 str
版本的 object 。
str
是内置字符串 class 。
sum
(iterable, /, start=0)
从 start 开始自左向右对 iterable 的项求和并返回总计值。 iterable 的项通常为数字,而 start 值则不允许为字符串。
对某些用例来说,存在 sum()
的更好替代。 拼接字符串序列的更好更快方式是调用 ''.join(sequence)
。
在 3.8 版更改: start 形参可用关键字参数形式来指定。
- class
super
([type[, object-or-type]])
返回一个代理对象,它会将方法调用委托给 type 的父类或兄弟类。 这对于访问已在类中被重载的继承方法很有用。
object-or-type 确定用于搜索的 method resolution order。 搜索会从 type 之后的类开始。
举例来说,如果 object-or-type 的 __mro__
为 D -> B -> C -> A -> object
并且 type 的值为 B
,则 super()
将会搜索 C -> A -> object
。
object-or-type 的 __mro__
属性列出了 getattr()
和 super()
所共同使用的方法解析搜索顺序。 该属性是动态的,可以在任何继承层级结构发生更新的时候被改变。
如果省略第二个参数,则返回的超类对象是未绑定的。 如果第二个参数为一个对象,则 isinstance(obj, type)
必须为真值。 如果第二个参数为一个类型,则 issubclass(type2, type)
必须为真值(这适用于类方法)。
super 有两个典型用例。 在具有单继承的类层级结构中,super 可用来引用父类而不必显式地指定它们的名称,从而令代码更易维护。 这种用法与其他编程语言中 super 的用法非常相似。
第二个用例是在动态执行环境中支持协作多重继承。 此用例为 Python 所独有而不存在于静态编码语言或仅支持单继承的语言当中。 这使用实现“菱形图”成为可能,即有多个基类实现相同的方法。 好的设计强制要求这样的方法在每个情况下都具有相同的调用签名(因为调用顺序是在运行时确定的,也因为这个顺序要适应类层级结构的更改,还因为这个顺序可能包括在运行时之前未知的兄弟类)。
对于以上两个用例,典型的超类调用看起来是这样的:
class C(B):
def method(self, arg):
super().method(arg)# This does the same thing as:
# super(C, self).method(arg)
除了方法查找之外,super()
也可用于属性查找。 一个可能的应用场合是在上级或同级类中调用 描述器。
请注意 super()
是作为显式加点属性查找的绑定过程的一部分来实现的,例如 super().__getitem__(name)
。 它做到这一点是通过实现自己的 __getattribute__()
方法,这样就能以可预测的顺序搜索类,并且支持协作多重继承。 对应地,super()
在像 super()[name]
这样使用语句或操作符进行隐式查找时则未被定义。
还要注意的是,除了零个参数的形式以外,super()
并不限于在方法内部使用。 两个参数的形式明确指定参数并进行相应的引用。 零个参数的形式仅适用于类定义内部,因为编译器需要填入必要的细节以正确地检索到被定义的类,还需要让普通方法访问当前实例。
对于有关如何使用 super()
来如何设计协作类的实用建议。
- class
tuple
([iterable])
虽然被称为函数,但 tuple
实际上是一个不可变的序列类型
class
type
(object)class
type
(name, bases, dict, **kwds)
传入一个参数时,返回 object 的类型。 返回值是一个 type 对象,通常与 object.__class__
所返回的对象相同。
推荐使用 isinstance()
内置函数来检测对象的类型,因为它会考虑子类的情况。
传入三个参数时,返回一个新的 type 对象。 这在本质上是 class
语句的一种动态形式,name 字符串即类名并会成为 __name__
属性;bases 元组包含基类并会成为 __bases__
属性;如果为空则会添加所有类的终极基类 object
。 dict 字典包含类主体的属性和方法定义;它在成为 __dict__
属性之前可能会被拷贝或包装。 下面两条语句会创建相同的 type
对象:
>>>class X:
... a =1
...
>>> X = type('X',(), dict(a=1))
提供给三参数形式的关键字参数会被传递给适当的元类机制 (通常为 __init_subclass__()
),相当于类定义中关键字 (除了 metaclass) 的行为方式。
在 3.6 版更改: type
的子类如果未重载 type.__new__
,将不再能使用一个参数的形式来获取对象的类型。
vars
([object])
返回模块、类、实例或任何其它具有 __dict__
属性的对象的 __dict__
属性。
模块和实例这样的对象具有可更新的 __dict__
属性;但是,其它对象的 __dict__
属性可能会设为限制写入(例如,类会使用 types.MappingProxyType
来防止直接更新字典)。
不带参数时,vars()
的行为类似 locals()
。 请注意,locals 字典仅对于读取起作用,因为对 locals 字典的更新会被忽略。
如果指定了一个对象但它没有 __dict__
属性(例如,当它所属的类定义了 __slots__
属性时)则会引发 TypeError
异常。
zip
(\iterables, strict=False*)
在多个迭代器上并行迭代,从每个迭代器返回一个数据项组成元组。
示例:
>>>for item in zip([1,2,3],['sugar','spice','everything nice']):
...print(item)
...
(1,'sugar')
(2,'spice')
(3,'everything nice')
更正式的说法: zip()
返回元组的迭代器,其中第 i 个元组包含的是每个参数迭代器的第 i 个元素。
不妨换一种方式认识 zip()
:它会把行变成列,把列变成行。这类似于 矩阵转置 。
zip()
是延迟执行的:直至迭代时才会对元素进行处理,比如 for
循环或放入 list
中。
值得考虑的是,传给 zip()
的可迭代对象可能长度不同;有时是有意为之,有时是因为准备这些对象的代码存在错误。Python 提供了三种不同的处理方案:
默认情况下,
zip()
在最短的迭代完成后停止。较长可迭代对象中的剩余项将被忽略,结果会裁切至最短可迭代对象的长度:>>> list(zip(range(3),['fee','fi','fo','fum'])) [(0,'fee'),(1,'fi'),(2,'fo')]
通常
zip()
用于可迭代对象等长的情况下。这时建议用strict=True
的选项。输出与普通的zip()
相同:。>>> list(zip(('a','b','c'),(1,2,3), strict=True)) [('a',1),('b',2),('c',3)]
与默认行为不同的是,它会检查可迭代对象的长度是否相同,如果不相同则触发
ValueError
。>>> list(zip(range(3),['fee','fi','fo','fum'], strict=True)) Traceback(most recent call last): ... ValueError: zip() argument 2is longer than argument 1
如果未指定
strict=True
参数,所有导致可迭代对象长度不同的错误都会被抑制,这可能会在程序的其他地方表现为难以发现的错误。为了让所有的可迭代对象具有相同的长度,长度较短的可用常量进行填充。这可由
itertools.zip_longest()
来完成。
极端例子是只有一个可迭代对象参数,zip()
会返回一个一元组的迭代器。如果未给出参数,则返回一个空的迭代器。
小技巧:
可确保迭代器的求值顺序是从左到右的。这样就能用
zip(*[iter(s)]*n, strict=True)
将数据列表按长度 n 进行分组。这将重复 相同 的迭代器n
次,输出的每个元组都包含n
次调用迭代器的结果。这样做的效果是把输入拆分为长度为 n 的块。zip()
与*
运算符相结合可以用来拆解一个列表:>>> x =[1,2,3] >>> y =[4,5,6] >>> list(zip(x, y)) [(1,4),(2,5),(3,6)] >>> x2, y2 = zip(*zip(x, y)) >>> x == list(x2) and y == list(y2) True
在 3.10 版更改: 增加了 strict
参数。
__import__
(name, globals=None, locals=None, fromlist=(), level=0)
注解
与 importlib.import_module()
不同,这是一个日常 Python 编程中不需要用到的高级函数。
此函数会由 import
语句发起调用。 它可以被替换 (通过导入 builtins
模块并赋值给 builtins.__import__
) 以便修改 import
语句的语义,但是 强烈 不建议这样做,因为使用导入钩子 (参见 PEP 302) 通常更容易实现同样的目标,并且不会导致代码问题,因为许多代码都会假定所用的是默认实现。 同样也不建议直接使用 __import__()
而应该用 importlib.import_module()
。
本函数会导入模块 name*,利用 *globals 和 locals 来决定如何在包的上下文中解释该名称。fromlist 给出了应从 name 模块中导入的对象或子模块的名称。标准的实现代码完全不会用到 locals 参数,只用到了 globals 用于确定 import
语句所在的包上下文。
level 指定是使用绝对还是相对导入。 0
(默认值) 意味着仅执行绝对导入。 level 为正数值表示相对于模块调用 __import__()
的目录,将要搜索的父目录层数 (详情参见 PEP 328)。
当 name 变量的形式为 package.module
时,通常将会返回最高层级的包(第一个点号之前的名称),而 不是 以 name 命名的模块。 但是,当给出了非空的 fromlist 参数时,则将返回以 name 命名的模块。
例如,语句 import spam
的结果将为与以下代码作用相同的字节码:
spam = __import__('spam', globals(), locals(),[],0)
语句 import spam.ham
的结果将为以下调用:
spam = __import__('spam.ham', globals(), locals(),[],0)
请注意在这里 __import__()
是如何返回顶层模块的,因为这是通过 import
语句被绑定到特定名称的对象。
另一方面,语句 from spam.ham import eggs, sausage as saus
的结果将为
_temp = __import__('spam.ham', globals(), locals(),['eggs','sausage'],0)
eggs = _temp.eggs
saus = _temp.sausage
在这里, spam.ham
模块会由 __import__()
返回。 要导入的对象将从此对象中提取并赋值给它们对应的名称。
如果您只想按名称导入模块(可能在包中),请使用 importlib.import_module()
在 3.3 版更改: level 的值不再支持负数(默认值也修改为0)。
在 3.9 版更改: 当使用了命令行参数 -E
或 -I
时,环境变量 PYTHONCASEOK
现在将被忽略。
内置常量
有少数的常量存在于内置命名空间中。 它们是:
False
bool
类型的假值。 给 False
赋值是非法的并会引发 SyntaxError
。
True
bool
类型的真值。 给 True
赋值是非法的并会引发 SyntaxError
。
None
通常被用来代表空值的对象,例如在未向某个函数传入默认参数时。 给 None
赋值是非法的并会引发 SyntaxError
。 None
是 NoneType
类型的唯一实例。
NotImplemented
应当由双目运算特殊方法(如 __eq__()
, __lt__()
, __add__()
, __rsub__()
等)返回的特殊值,用于表明运算没有针对其他类型的实现;也可由原地双目运算特殊方法(如 __imul__()
, __iand__()
等)出于同样的目的而返回。 它不应在布尔运算中被求值。 NotImplemented
是 types.NotImplementedType
类型的唯一实例。
注解
当二进制(或就地)方法返回NotImplemented
时,解释器将尝试对另一种类型(或其他一些回滚操作,取决于运算符)的反射操作。 如果所有尝试都返回NotImplemented
,则解释器将引发适当的异常。 错误返回的NotImplemented
将导致误导性错误消息或返回到Python代码中的NotImplemented
值。
注解
NotImplementedError
和 NotImplemented
不可互换,即使它们有相似的名称和用途。
在 3.9 版更改: 作为布尔值来解读 NotImplemented
已被弃用。 虽然它目前会被解读为真值,但将同时发出 DeprecationWarning
。 它将在未来的 Python 版本中引发 TypeError
。
Ellipsis
与省略号字面值 “...
“ 相同。 该特殊值主要是与用户定义的容器数据类型的扩展切片语法结合使用。 Ellipsis
是 types.EllipsisType
类型的唯一实例。
__debug__
如果 Python 没有以 -O
选项启动,则此常量为真值。
注解
变量名 None
,False
,True
和 __ debug__
无法重新赋值(赋值给它们,即使是属性名,将引发 SyntaxError
),所以它们可以被认为是“真正的”常数。
由 site
模块添加的常量
site
模块(在启动期间自动导入,除非给出 -S
命令行选项)将几个常量添加到内置命名空间。 它们对交互式解释器 shell 很有用,并且不应在程序中使用。
quit
(code=None)exit
(code=None)
当打印此对象时,会打印出一条消息,例如“Use quit() or Ctrl-D (i.e. EOF) to exit”,当调用此对象时,将使用指定的退出代码来引发 SystemExit
。
copyright
credits
打印或调用的对象分别打印版权或作者的文本。
license
当打印此对象时,会打印出一条消息“Type license() to see the full license text”,当调用此对象时,将以分页形式显示完整的许可证文本(每次显示一屏)。
内置类型
以下部分描述了解释器中内置的标准类型。
主要内置类型有数字、序列、映射、类、实例和异常。
有些多项集类是可变的。 它们用于添加、移除或重排其成员的方法将原地执行,并不返回特定的项,绝对不会返回多项集实例自身而是返回 None
。
有些操作受多种对象类型的支持;特别地,实际上所有对象都可以比较是否相等、检测逻辑值,以及转换为字符串(使用 repr()
函数或略有差异的 str()
函数)。 后一个函数是在对象由 print()
函数输出时被隐式地调用的。
逻辑值检测
任何对象都可以进行逻辑值的检测,以便在 if
或 while
作为条件或是作为下文所述布尔运算的操作数来使用。
一个对象在默认情况下均被视为真值,除非当该对象被调用时其所属类定义了 __bool__()
方法且返回 False
或是定义了 __len__()
方法且返回零。 下面基本完整地列出了会被视为假值的内置对象:
- 被定义为假值的常量:
None
和False
。 - 任何数值类型的零:
0
,0.0
,0j
,Decimal(0)
,Fraction(0, 1)
- 空的序列和多项集:
''
,()
,[]
,{}
,set()
,range(0)
产生布尔值结果的运算和内置函数总是返回 0
或 False
作为假值,1
或 True
作为真值,除非另行说明。 (重要例外:布尔运算 or
和 and
总是返回其中一个操作数。)
布尔运算 —- and
, or
, not
这些属于布尔运算,按优先级升序排列:
运算 | 结果: | 备注 |
---|---|---|
x or y |
if x is false, then y, else x | (1) |
x and y |
if x is false, then x, else y | (2) |
not x |
if x is false, then True , else False |
(3) |
注释:
- 这是个短路运算符,因此只有在第一个参数为假值时才会对第二个参数求值。
- 这是个短路运算符,因此只有在第一个参数为真值时才会对第二个参数求值。
not
的优先级比非布尔运算符低,因此not a == b
会被解读为not (a == b)
而a == not b
会引发语法错误。
比较运算
在 Python 中有八种比较运算符。 它们的优先级相同(比布尔运算的优先级高)。 比较运算可以任意串连;例如,x < y <= z
等价于 x < y and y <= z
,前者的不同之处在于 y 只被求值一次(但在两种情况下当 x < y
结果为假值时 z 都不会被求值)。
此表格汇总了比较运算:
运算 | 含意 |
---|---|
< |
严格小于 |
<= |
小于或等于 |
> |
严格大于 |
>= |
大于或等于 |
== |
等于 |
!= |
不等于 |
is |
对象标识 |
is not |
否定的对象标识 |
除不同的数字类型外,不同类型的对象不能进行相等比较。==
运算符总有定义,但对于某些对象类型(例如,类对象),它等于 is
。其他 <
、<=
、>
和 >=
运算符仅在有意义的地方定义。例如,当参与比较的参数之一为复数时,它们会抛出 TypeError
异常。
具有不同标识的类的实例比较结果通常为不相等,除非类定义了 __eq__()
方法。
一个类实例不能与相同类或的其他实例或其他类型的对象进行排序,除非该类定义了足够多的方法,包括 __lt__()
, __le__()
, __gt__()
以及 __ge__()
(而如果你想实现常规意义上的比较操作,通常只要有 __lt__()
和 __eq__()
就可以了)。
is
和 is not
运算符无法自定义;并且它们可以被应用于任意两个对象而不会引发异常。
还有两种具有相同语法优先级的运算 in
和 not in
,它们被 iterable 或实现了 __contains__()
方法的类型所支持。
数字类型 —- int
, float
, complex
存在三种不同的数字类型: 整数, 浮点数 和 复数*。 此外,布尔值属于整数的子类型。 整数具有无限的精度。 浮点数通常使用 C 中的 double 来实现;有关你的程序运行所在机器上浮点数的精度和内部表示法可在 sys.float_info
中查看。 复数包含实部和虚部,分别以一个浮点数表示。 要从一个复数 *z 中提取这两个部分,可使用 z.real
和 z.imag
。 (标准库包含附加的数字类型,如表示有理数的 fractions.Fraction
以及以用户定制精度表示浮点数的 decimal.Decimal
。)
数字是由数字字面值或内置函数与运算符的结果来创建的。 不带修饰的整数字面值(包括十六进制、八进制和二进制数)会生成整数。 包含小数点或幂运算符的数字字面值会生成浮点数。 在数字字面值末尾加上 'j'
或 'J'
会生成虚数(实部为零的复数),你可以将其与整数或浮点数相加来得到具有实部和虚部的复数。
Python 完全支持混合运算:当一个二元算术运算符的操作数有不同数值类型时,”较窄”类型的操作数会拓宽到另一个操作数的类型,其中整数比浮点数窄,浮点数比复数窄。不同类型的数字之间的比较,同比较这些数字的精确值一样。
构造函数 int()
、 float()
和 complex()
可以用来构造特定类型的数字。
所有数字类型(复数除外)都支持下列运算:
运算 | 结果: | 备注 | 完整文档 |
---|---|---|---|
x + y |
x 和 y 的和 | ||
x - y |
x 和 y 的差 | ||
x * y |
x 和 y 的乘积 | ||
x / y |
x 和 y 的商 | ||
x // y |
x 和 y 的商数 | (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 和虚部 im 的复数。im 默认为0。 | (6) | complex() |
c.conjugate() |
复数 c 的共轭 | ||
divmod(x, y) |
(x // y, x % y) |
(2) | divmod() |
pow(x, y) |
x 的 y 次幂 | (5) | pow() |
x ** y |
x 的 y 次幂 | (5) |
注释:
也称为整数除法。 结果值是一个整数,但结果的类型不一定是 int。 运算结果总是向负无穷的方向舍入:
1//2
为0
,(-1)//2
为-1
,1//(-2)
为-1
而(-1)//(-2)
为0
。不可用于复数。 而应在适当条件下使用
abs()
转换为浮点数。从浮点数转换为整数会被舍入或是像在 C 语言中一样被截断。
float 也接受字符串 “nan” 和附带可选前缀 “+” 或 “-“ 的 “inf” 分别表示非数字 (NaN) 以及正或负无穷。
Python 将
pow(0, 0)
和0 ** 0
定义为1
,这是编程语言的普遍做法。接受的数字字面值包括数码
0
到9
或任何等效的 Unicode 字符(具有Nd
特征属性的代码点)。请参阅 https://www.unicode.org/Public/13.0.0/ucd/extracted/DerivedNumericType.txt 查看具有
Nd
特征属性的代码点的完整列表。
所有 numbers.Real
类型 (int
和 float
) 还包括下列运算:
运算 | 结果: |
---|---|
math.trunc(x) |
x 截断为 Integral |
round(x[, n\]) |
x 舍入到 n 位小数,半数值会舍入到偶数。 如果省略 n,则默认为 0。 |
math.floor(x) |
<= x 的最大 Integral |
math.ceil(x) |
>= x 的最小 Integral |
整数类型的按位运算
按位运算只对整数有意义。 计算按位运算的结果,就相当于使用无穷多个二进制符号位对二的补码执行操作。
二进制按位运算的优先级全都低于数字运算,但又高于比较运算;一元运算 ~
具有与其他一元算术运算 (+
and -
) 相同的优先级。
此表格是以优先级升序排序的按位运算列表:
运算 | 结果: | 备注 |
---|---|---|
`x | y` | x 和 y 按位 或 |
x ^ y |
x 和 y 按位 异或 | (4) |
x & y |
x 和 y 按位 与 | (4) |
x << n |
x 左移 n 位 | (1)(2) |
x >> n |
x 右移 n 位 | (1)(3) |
~x |
x 逐位取反 |
注释:
- 负的移位数是非法的,会导致引发
ValueError
。 - 左移 n 位等价于乘以
pow(2, n)
。 - 右移 n 位等价于除以
pow(2, n)
,作向下取整除法。 - 使用带有至少一个额外符号扩展位的有限个二进制补码表示(有效位宽度为
1 + max(x.bit_length(), y.bit_length())
或以上)执行这些计算就足以获得相当于有无数个符号位时的同样结果。
整数类型的附加方法
int 类型实现了 numbers.Integral
abstract base class。 此外,它还提供了其他几个方法:
int.bit_length
()
返回以二进制表示一个整数所需要的位数,不包括符号位和前面的零:
>>> n = -37
>>> bin(n)
'-0b100101'
>>> n.bit_length()
6
更准确地说,如果 x
非零,则 x.bit_length()
是使得 2**(k-1) <= abs(x) < 2**k
的唯一正整数 k
。 同样地,当 abs(x)
小到足以具有正确的舍入对数时,则 k = 1 + int(log(abs(x), 2))
。 如果 x
为零,则 x.bit_length()
返回 0
。
等价于:
def bit_length(self):
s = bin(self) # 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
()
Return the number of ones in the binary representation of the absolute value of the integer. This is also known as the population count. Example:
>>> 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 参数确定是否使用二的补码来表示整数。 如果 signed 为 False
并且给出的是负整数,则会引发 OverflowError
。 signed 的默认值为 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
abstract base class。 float 还具有以下附加方法。
float.as_integer_ratio
()
返回一对整数,其比率正好等于原浮点数并且分母为正数。 无穷大会引发 OverflowError
而 NaN 则会引发 ValueError
。
float.is_integer
()
如果 float 实例可用有限位整数表示则返回 True
,否则返回 False
:
>>> (-2.0).is_integer()
True
>>> (3.2).is_integer()
False
两个方法均支持与十六进制数字符串之间的转换。 由于 Python 浮点数在内部存储为二进制数,因此浮点数与 十进制数 字符串之间的转换往往会导致微小的舍入错误。 而十六进制数字符串却允许精确地表示和描述浮点数。 这在进行调试和数值工作时非常有用。
float.hex
()
以十六进制字符串的形式返回一个浮点数表示。 对于有限浮点数,这种表示法将总是包含前导的 0x
和尾随的 p
加指数。
classmethod float.fromhex
(s)
返回以十六进制字符串 s 表示的浮点数的类方法。 字符串 s 可以带有前导和尾随的空格。
请注意 float.hex()
是实例方法,而 float.fromhex()
是类方法。
十六进制字符串采用的形式为:
[sign] ['0x'] integer ['.' fraction] ['p' exponent]
可选的 sign
可以是 +
或 -
,integer
和 fraction
是十六进制数码组成的字符串,exponent
是带有可选前导符的十进制整数。 大小写没有影响,在 integer 或 fraction 中必须至少有一个十六进制数码。 此语法类似于 C99 标准的 6.4.4.2 小节中所描述的语法,也是 Java 1.5 以上所使用的语法。 特别地,float.hex()
的输出可以用作 C 或 Java 代码中的十六进制浮点数字面值,而由 C 的 %a
格式字符或 Java 的 Double.toHexString
所生成的十六进制数字符串由为 float.fromhex()
所接受。
请注意 exponent 是十进制数而非十六进制数,它给出要与系数相乘的 2 的幂次。 例如,十六进制数字符串 0x3.a7p10
表示浮点数 (3 + 10./16 + 7./16**2) * 2.0**10
即 3740.0
:
>>> float.fromhex('0x3.a7p10')
3740.0
对 3740.0
应用反向转换会得到另一个代表相同数值的十六进制数字符串:
>>> float.hex(3740.0)
'0x1.d380000000000p+11'
数字类型的哈希运算
对于可能为不同类型的数字 x
和 y
,要求 x == y
时必定 hash(x) == hash(y)
。 为了便于在各种数字类型 (包括 int
, float
, decimal.Decimal
和 fractions.Fraction
) 上实现并保证效率,Python 对数字类型的哈希运算是基于为任意有理数定义统一的数学函数,因此该运算对 int
和 fractions.Fraction
的全部实例,以及 float
和 decimal.Decimal
的全部有限实例均可用。 从本质上说,此函数是通过以一个固定质数 P
进行 P
降模给出的。 P
的值在 Python 中可以 sys.hash_info
的 modulus
属性的形式被访问。
CPython implementation detail: 目前所用的质数设定,在 C long 为 32 位的机器上 P = 2**31 - 1
而在 C long 为 64 位的机器上 P = 2**61 - 1
。
详细规则如下所述:
- 如果
x = m / n
是一个非负的有理数且n
不可被P
整除,则定义hash(x)
为m * invmod(n, P) % P
,其中invmod(n, P)
是对n
模P
取反。 - 如果
x = m / n
是一个非负的有理数且n
可被P
整除(但m
不能)则n
不能对P
降模,以上规则不适用;在此情况下则定义hash(x)
为常数值sys.hash_info.inf
。 - 如果
x = m / n
是一个负的有理数则定义hash(x)
为-hash(-x)
。 如果结果哈希值为-1
则将其替换为-2
。 - The particular values
sys.hash_info.inf
and-sys.hash_info.inf
are used as hash values for positive infinity or negative infinity (respectively). - 对于一个
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
迭代器类型
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 的 generator 提供了一种实现迭代器协议的便捷方式。 如果容器对象 __iter__()
方法被实现为一个生成器,它将自动返回一个迭代器对象(从技术上说是一个生成器对象),该对象提供 __iter__()
和 __next__()
方法。
序列类型 —- list
, tuple
, range
有三种基本序列类型:list, tuple 和 range 对象。
通用序列操作
大多数序列类型,包括可变类型和不可变类型都支持下表中的操作。 collections.abc.Sequence
ABC 被提供用来更容易地在自定义序列类型上正确地实现这些操作。
此表按优先级升序列出了序列操作。 在表格中,s 和 t 是具有相同类型的序列,n, i, j 和 k 是整数而 x 是任何满足 s 所规定的类型和值限制的任意对象。
in
和 not in
操作具有与比较操作相同的优先级。 +
(拼接) 和 *
(重复) 操作具有与对应数值运算相同的优先级。
运算 | 结果: | 备注 |
---|---|---|
x in s |
如果 s 中的某项等于 x 则结果为 True ,否则为 False |
(1) |
x not in s |
如果 s 中的某项等于 x 则结果为 False ,否则为 True |
(1) |
s + t |
s 与 t 相拼接 | (6)(7) |
s * n 或 n s |
相当于 s 与自身进行 n 次拼接 | (2)(7) |
s[i] |
s 的第 i 项,起始为 0 | (3) |
s[i:j] |
s 从 i 到 j 的切片 | (3)(4) |
s[i:j:k] |
s 从 i 到 j 步长为 k 的切片 | (3)(5) |
len(s) |
s 的长度 | |
min(s) |
s 的最小项 | |
max(s) |
s 的最大项 | |
s.index(x[, i[, j]]) |
x 在 s 中首次出现项的索引号(索引号在 i 或其后且在 j 之前) | (8) |
s.count(x) |
x 在 s 中出现的总次数 |
相同类型的序列也支持比较。 特别地,tuple 和 list 的比较是通过比较对应元素的字典顺序。 这意味着想要比较结果相等,则每个元素比较结果都必须相等,并且两个序列长度必须相同。
注释:
虽然
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
。s 从 i 到 j 的切片被定义为所有满足
i <= k < j
的索引号 k 的项组成的序列。 如果 i 或 j 大于len(s)
,则使用len(s)
。 如果 i 被省略或为None
,则使用0
。 如果 j 被省略或为None
,则使用len(s)
。 如果 i 大于等于 j,则切片为空。s 从 i 到 j 步长为 k 的切片被定义为所有满足
0 <= n < (j-i)/k
的索引号x = i + n*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
对象是可变的,并且具有高效的重分配机制 - 如果拼接
tuple
对象,请改为扩展list
类 - 对于其它类型,请查看相应的文档
- 如果拼接
某些序列类型 (例如
range
) 仅支持遵循特定模式的项序列,因此并不支持序列拼接或重复。当 x 在 s 中找不到时
index
会引发ValueError
。 不是所有实现都支持传入额外参数 i 和 j。 这两个参数允许高效地搜索序列的子序列。 传入这两个额外参数大致相当于使用s[i:j].index(x)
,但是不会复制任何数据,并且返回的索引是相对于序列的开头而非切片的开头。
不可变序列类型
不可变序列类型普遍实现而可变序列类型未实现的唯一操作就是对 hash()
内置函数的支持。
这种支持允许不可变类型,例如 tuple
实例被用作 dict
键,以及存储在 set
和 frozenset
实例中。
尝试对包含有不可哈希值的不可变序列进行哈希运算将会导致 TypeError
。
可变序列类型
以下表格中的操作是在可变序列类型上定义的。 collections.abc.MutableSequence
ABC 被提供用来更容易地在自定义序列类型上正确实现这些操作。
表格中的 s 是可变序列类型的实例,t 是任意可迭代对象,而 x 是符合对 s 所规定类型与值限制的任何对象 (例如,bytearray
仅接受满足 0 <= x <= 255
值限制的整数)。
运算 | 结果: | 备注 |
---|---|---|
s[i] = x |
将 s 的第 i 项替换为 x | |
s[i:j] = t |
将 s 从 i 到 j 的切片替换为可迭代对象 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() or s.pop(i) |
提取在 i 位置上的项,并将其从 s 中移除 | (2) |
s.remove(x) |
删除 s 中第一个 s[i] 等于 x 的项目。 |
(3) |
s.reverse() |
就地将列表中的元素逆序。 | (4) |
注释:
t 必须与它所替换的切片具有相同的长度。
可选参数 i 默认为
-1
,因此在默认情况下会移除并返回最后一项。当在 s 中找不到 x 时
remove()
操作会引发ValueError
。当反转大尺寸序列时
reverse()
方法会原地修改该序列以保证空间经济性。 为提醒用户此操作是通过间接影响进行的,它并不会返回反转后的序列。包括
clear()
和copy()
是为了与不支持切片操作的可变容器 (例如dict
和set
) 的接口保持一致。copy()
不是collections.abc.MutableSequence
ABC 的一部分,但大多数具体的可变序列类都提供了它。3.3 新版功能:
clear()
和copy()
方法。n 值为一个整数,或是一个实现了
__index__()
的对象。 n 值为零或负数将清空序列。 序列中的项不会被拷贝;它们会被多次引用,正如 通用序列操作 中有关s * n
的说明。
列表
列表是可变序列,通常用于存放同类项目的集合(其中精确的相似程度将根据应用而变化)。
class list
([iterable])
可以用多种方式构建列表:
- 使用一对方括号来表示空列表:
[]
- 使用方括号,其中的项以逗号分隔:
[a]
,[a, b, c]
- 使用列表推导式:
[x for x in iterable]
- 使用类型的构造器:
list()
或list(iterable)
构造器将构造一个列表,其中的项与 iterable 中的项具有相同的的值与顺序。 iterable 可以是序列、支持迭代的容器或其它可迭代对象。 如果 iterable 已经是一个列表,将创建并返回其副本,类似于 iterable[:]
。 例如,list('abc')
返回 ['a', 'b', 'c']
而 list( (1, 2, 3) )
返回 [1, 2, 3]
。 如果没有给出参数,构造器将创建一个空列表 []
。
其它许多操作也会产生列表,包括 sorted()
内置函数。
列表实现了所有 一般 和 可变 序列的操作。 列表还额外提供了以下方法:
sort
(**, key=None, reverse=False*)此方法会对列表进行原地排序,只使用
<
来进行各项间比较。 异常不会被屏蔽 —— 如果有任何比较操作失败,整个排序操作将失败(而列表可能会处于被部分修改的状态)。sort()
接受两个仅限以关键字形式传入的参数 (仅限关键字参数):key 指定带有一个参数的函数,用于从每个列表元素中提取比较键 (例如
key=str.lower
)。 对应于列表中每一项的键会被计算一次,然后在整个排序过程中使用。 默认值None
表示直接对列表项排序而不计算一个单独的键值。可以使用
functools.cmp_to_key()
将 2.x 风格的 cmp 函数转换为 key 函数。reverse 为一个布尔值。 如果设为
True
,则每个列表元素将按反向顺序比较进行排序。当顺序大尺寸序列时此方法会原地修改该序列以保证空间经济性。 为提醒用户此操作是通过间接影响进行的,它并不会返回排序后的序列(请使用
sorted()
显示地请求一个新的已排序列表实例)。sort()
方法确保是稳定的。 如果一个排序确保不会改变比较结果相等的元素的相对顺序就称其为稳定的 —- 这有利于进行多重排序(例如先按部门、再接薪级排序)。CPython implementation detail: 在一个列表被排序期间,尝试改变甚至进行检测也会造成未定义的影响。 Python 的 C 实现会在排序期间将列表显示为空,如果发现列表在排序期间被改变将会引发
ValueError
。
元组
元组是不可变序列,通常用于储存异构数据的多项集(例如由 enumerate()
内置函数所产生的二元组)。 元组也被用于需要同构数据的不可变序列的情况(例如允许存储到 set
或 dict
的实例)。
class tuple
([iterable])
可以用多种方式构建元组:
- 使用一对圆括号来表示空元组:
()
- 使用一个后缀的逗号来表示单元组:
a,
或(a,)
- 使用以逗号分隔的多个项:
a, b, c
or(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))
则是在调用函数时附带一个三元组。
元组实现了所有 一般 序列的操作。
对于通过名称访问相比通过索引访问更清晰的异构数据多项集,collections.namedtuple()
可能是比简单元组对象更为合适的选择。
range 对象
range
类型表示不可变的数字序列,通常用于在 for
循环中循环指定的次数。
class range
(stop)
class range
(start, stop[, step])
range 构造器的参数必须为整数(可以是内置的 int
或任何实现了 __index__
特殊方法的对象)。 如果省略 step 参数,其默认值为 1
。 如果省略 start 参数,其默认值为 0
,如果 step 为零则会引发 ValueError
。
如果 step 为正值,确定 range r
内容的公式为 r[i] = start + step*i
其中 i >= 0
且 r[i] < stop
。
如果 step 为负值,确定 range 内容的公式仍然为 r[i] = start + step*i
,但限制条件改为 i >= 0
且 r[i] > stop
.
如果 r[0]
不符合值的限制条件,则该 range 对象为空。 range 对象确实支持负索引,但是会将其解读为从正索引所确定的序列的末尾开始索引。
元素绝对值大于 sys.maxsize
的 range 对象是被允许的,但某些特性 (例如 len()
) 可能引发 OverflowError
。
一些 range 对象的例子:
>>> 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))
[]
range 对象实现了 一般 序列的所有操作,但拼接和重复除外(这是由于 range 对象只能表示符合严格模式的序列,而重复和拼接通常都会违反这样的模式)。
start
start 形参的值 (如果该形参未提供则为
0
)stop
stop 形参的值
step
step 形参的值 (如果该形参未提供则为
1
)
range
类型相比常规 list
或 tuple
的优势在于一个 range
对象总是占用固定数量的(较小)内存,不论其所表示的范围有多大(因为它只保存了 start
, stop
和 step
值,并会根据需要计算具体单项或子范围的值)。
range 对象实现了 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
使用 ==
和 !=
检测 range 对象是否相等是将其作为序列来比较。 也就是说,如果两个 range 对象表示相同的值序列就认为它们是相等的。 (请注意比较结果相等的两个 range 对象可能会具有不同的 start
, stop
和 step
属性,例如 range(0) == range(2, 1, 3)
而 range(0, 3, 2) == range(0, 4, 2)
。)
在 3.2 版更改: 实现 Sequence ABC。 支持切片和负数索引。 使用 int
对象在固定时间内进行成员检测,而不是逐一迭代所有项。
在 3.3 版更改: 定义 ‘==’ 和 ‘!=’ 以根据 range 对象所定义的值序列来进行比较(而不是根据对象的标识)。
3.3 新版功能: start
, stop
和 step
属性。
参见
- linspace recipe 演示了如何实现一个延迟求值版本的适合浮点数应用的 range 对象。
文本序列类型 —- str
在 Python 中处理文本数据是使用 str
对象,也称为 字符串。 字符串是由 Unicode 码位构成的不可变 序列。 字符串字面值有多种不同的写法:
- 单引号:
'允许包含有 "双" 引号'
- 双引号:
"允许包含有 '单' 引号"
。 - 三重引号:
'''三重单引号'''
,"""三重双引号"""
使用三重引号的字符串可以跨越多行 —— 其中所有的空白字符都将包含在该字符串字面值中。
作为单一表达式组成部分,之间只由空格分隔的多个字符串字面值会被隐式地转换为单个字符串字面值。 也就是说,("spam " "eggs") == "spam eggs"
。
使用 r
(“raw”) 前缀来禁用大多数转义序列的处理。
字符串也可以通过使用 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)
返回 object.__str__()
,这是 object 的“非正式”或格式良好的字符串表示。 对于字符串对象,这是该字符串本身。 如果 object 没有 __str__()
方法,则 str()
将回退为返回 repr(object)
。
如果 encoding 或 errors 至少给出其中之一,则 object 应该是一个 bytes-like object (例如 bytes
或 bytearray
)。 在此情况下,如果 object 是一个 bytes
(或 bytearray
) 对象,则 str(bytes, encoding, errors)
等价于 bytes.decode(encoding, errors)
。 否则的话,会在调用 bytes.decode()
之前获取缓冲区对象下层的 bytes 对象。
将一个 bytes
对象传入 str()
而不给出 encoding 或 errors 参数的操作属于第一种情况, 将返回非正式的字符串表示(另请参阅 Python 的 -b
命令行选项)。 例如:
>>> str(b'Zoot!')
"b'Zoot!'"
字符串的方法
字符串实现了所有 一般 序列的操作,还额外提供了以下列出的一些附加方法。
字符串还支持两种字符串格式化样式,一种提供了很大程度的灵活性和可定制性 而另一种是基于 C printf
样式的格式化,它可处理的类型范围较窄,并且更难以正确使用,但对于它可处理的情况往往会更为快速 (printf 风格的字符串格式化)。
标准库的 文本处理服务 部分涵盖了许多其他模块,提供各种文本相关工具(例如包含于 re
模块中的正则表达式支持)。
str.capitalize
()
返回原字符串的副本,其首个字符大写,其余为小写。
在 3.8 版更改: 第一个字符现在被放入了 titlecase 而不是 uppercase。 这意味着复合字母类字符将只有首个字母改为大写,而再不是全部字符大写。
str.casefold
()
返回原字符串消除大小写的副本。 消除大小写的字符串可用于忽略大小写的匹配。
消除大小写类似于转为小写,但是更加彻底一些,因为它会移除字符串中的所有大小写变化形式。 例如,德语小写字母 'ß'
相当于 "ss"
。 由于它已经是小写了,lower()
不会对 'ß'
做任何改变;而 casefold()
则会将其转换为 "ss"
。
消除大小写算法的描述请参见 Unicode 标准的 3.13 节。
3.3 新版功能.
str.center
(width[, fillchar])
返回长度为 width 的字符串,原字符串在其正中。 使用指定的 fillchar 填充两边的空位(默认使用 ASCII 空格符)。 如果 width 小于等于 len(s)
则返回原字符串的副本。
str.count
(sub[, start[, end]])
返回子字符串 sub 在 [start, end*] 范围内非重叠出现的次数。 可选参数 *start 与 end 会被解读为切片表示法。
str.encode
(encoding=’utf-8’, errors=’strict’)
返回原字符串编码为字节串对象的版本。 默认编码为 'utf-8'
。 可以给出 errors 来设置不同的错误处理方案。 errors 的默认值为 'strict'
,表示编码错误会引发 UnicodeError
。 其他可用的值为 'ignore'
, 'replace'
, 'xmlcharrefreplace'
, 'backslashreplace'
以及任何其他通过 codecs.register_error()
注册的值。 要查看可用的编码列表。
By default, the errors argument is not checked for best performances, but only used at the first encoding error. Enable the Python Development Mode, or use a debug build to check errors.
在 3.1 版更改: 加入了对关键字参数的支持。
在 3.9 版更改: The errors is now checked in development mode and in debug mode.
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
。
注解
find()
方法应该只在你需要知道 sub 所在位置时使用。 要检查 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
类型 (例如: '{:n}'.format(1234)
) 来格式化数字 (int
, float
, complex
, decimal.Decimal
及其子类) 的时候,该函数会临时性地将 LC_CTYPE
区域设置为 LC_NUMERIC
区域以解码 localeconv()
的 decimal_point
和 thousands_sep
字段,如果它们是非 ASCII 字符或长度超过 1 字节的话,并且 LC_NUMERIC
区域会与 LC_CTYPE
区域不一致。 这个临时更改会影响其他线程。
在 3.7 版更改: 当使用 n
类型格式化数字时,该函数在某些情况下会临时性地将 LC_CTYPE
区域设置为 LC_NUMERIC
区域。
str.format_map
(mapping)
类似于 str.format(**mapping)
,不同之处在于 mapping
会被直接使用而不是复制到一个 dict
。 适宜使用此方法的一个例子是当 mapping
为 dict 的子类的情况:
>>> class Default(dict):
... def __missing__(self, key):
... return key
...
>>> '{name} was born in {country}'.format_map(Default(name='Guido'))
'Guido was born in country'
3.2 新版功能.
str.index
(sub[, start[, end]])
类似于 find()
,但在找不到子类时会引发 ValueError
。
str.isalnum
()
如果字符串中的所有字符都是字母或数字且至少有一个字符,则返回 True
, 否则返回 False
。 如果 c.isalpha()
, c.isdecimal()
, c.isdigit()
,或 c.isnumeric()
之中有一个返回 True
,则字符c
是字母或数字。
str.isalpha
()
如果字符串中的所有字符都是字母,并且至少有一个字符,返回 True
,否则返回 False
。字母字符是指那些在 Unicode 字符数据库中定义为 “Letter” 的字符,即那些具有 “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 ,即阿拉伯字母数字0 。 严格地讲,十进制字符是 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.islower
()
如果字符串中至少有一个区分大小写的字符 且此类字符均为小写则返回 True
,否则返回 False
。
str.isnumeric
()
如果字符串中至少有一个字符且所有字符均为数值字符则返回 True
,否则返回 False
。 数值字符包括数字字符,以及所有在 Unicode 中设置了数值特性属性的字符,例如 U+2155, VULGAR FRACTION ONE FIFTH。 正式的定义为:数值字符就是具有特征属性值 Numeric_Type=Digit, Numeric_Type=Decimal 或 Numeric_Type=Numeric 的字符。
str.isprintable
()
如果字符串中所有字符均为可打印字符或字符串为空则返回 True
,否则返回 False
。 不可打印字符是在 Unicode 字符数据库中被定义为 “Other” 或 “Separator” 的字符,例外情况是 ASCII 空格字符 (0x20) 被视作可打印字符。 (请注意在此语境下可打印字符是指当对一个字符串发起调用 repr()
时不必被转义的字符。 它们与字符串写入 sys.stdout
或 sys.stderr
时所需的处理无关。)
str.isspace
()
如果字符串中只有空白字符且至少有一个字符则返回 True
,否则返回 False
。
空白 字符是指在 Unicode 字符数据库 中主要类别为 Zs
(“Separator, space”) 或所属双向类为 WS
, B
或 S
的字符。
str.istitle
()
如果字符串中至少有一个字符且为标题字符串则返回 True
,例如大写字符之后只能带非大写字符而小写字符必须有大写字符打头。 否则返回 False
。
str.isupper
()
如果字符串中至少有一个区分大小写的字符 且此类字符均为大写则返回 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
()
返回原字符串的副本,其所有区分大小写的字符 均转换为小写。
所用转换小写算法的描述请参见 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, /)
如果字符串以 前缀 字符串开头,返回 string[len(prefix):]
。否则,返回原始字符串的副本:
>>> 'TestHook'.removeprefix('Test')
'Hook'
>>> 'BaseTestCase'.removeprefix('Test')
'BaseTestCase'
3.9 新版功能.
str.removesuffix
(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'
要删除单个后缀字符串,而不是全部给定集合中的字符。 例如:
>>> '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])
返回由原字符串中各行组成的列表,在行边界的位置拆分。 结果列表中不包含行边界,除非给出了 keepends 且为真值。
此方法会以下列行边界进行拆分。 特别地,行边界是 universal newlines 的一个超集。
表示符 | 描述 |
---|---|
\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"
可以使用正则表达式来构建针对撇号的特别处理:
>>> 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__()
来实现索引操作的对象,通常为 mapping 或 sequence。 当以 Unicode 码位序号(整数)为索引时,转换表对象可以做以下任何一种操作:返回 Unicode 序号或字符串,将字符映射为一个或多个字符;返回 None
,将字符从结果字符串中删除;或引发 LookupError
异常,将字符映射为其自身。
你可以使用 str.maketrans()
基于不同格式的字符到字符映射来创建一个转换映射表。
str.upper
()
返回原字符串的副本,其中所有区分大小写的字符 均转换为大写。 请注意如果 s
包含不区分大小写的字符或者如果结果字符的 Unicode 类别不是 “Lu” (Letter, uppercase) 而是 “Lt” (Letter, titlecase) 则 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 可以为一个非元组对象。 否则的话,values 必须或者是一个包含项数与格式字符串中指定的转换符项数相同的元组,或者是一个单独映射对象(例如字典)。
转换标记符包含两个或更多字符并具有以下组成,且必须遵循此处规定的顺序:
'%'
字符,用于标记转换符的起始。- 映射键(可选),由加圆括号的字符序列组成 (例如
(somename)
)。 - 转换旗标(可选),用于影响某些转换类型的结果。
- 最小字段宽度(可选)。 如果指定为
'*'
(星号),则实际宽度会从 values 元组的下一元素中读取,要转换的对象则为最小字段宽度和可选的精度之后的元素。 - 精度(可选),以在
'.'
(点号) 之后加精度值的形式给出。 如果指定为'*'
(星号),则实际精度会从 values 元组的下一元素中读取,要转换的对象则为精度之后的元素。 - 长度修饰符(可选)。
- 转换类型。
当右边的参数为一个字典(或其他映射类型)时,字符串中的格式 必须 包含加圆括号的映射键,对应 '%'
字符之后字典中的每一项。 映射键将从映射中选取要格式化的值。 例如:
>>> print('%(language)s has %(number)03d quote types.' %
... {'language': "Python", "number": 2})
Python has 002 quote types.
在此情况下格式中不能出现 *
标记符(因其需要一个序列类的参数列表)。
转换旗标为:
旗标 | 含意 |
---|---|
‘#’ |
值的转换将使用“替代形式”(具体定义见下文)。 |
‘0’ |
转换将为数字值填充零字符。 |
‘-‘ |
转换值将靠左对齐(如果同时给出 ‘0’ 转换,则会覆盖后者)。 |
‘ ‘ |
(空格) 符号位转换产生的正数(或空字符串)前将留出一个空格。 |
‘+’ |
符号字符 (‘+’ 或 ‘-‘ ) 将显示于转换结果的开头(会覆盖 “空格” 旗标)。 |
可以给出长度修饰符 (h
, l
或 L
),但会被忽略,因为对 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) |
‘%’ |
不转换参数,在结果中输出一个 ‘%’ 字符。 |
注释:
此替代形式会在第一个数码之前插入标示八进制数的前缀 (
'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 双精度浮点值。
bytes 对象
bytes 对象是由单个字节构成的不可变序列。 由于许多主要二进制协议都基于 ASCII 文本编码,因此 bytes 对象提供了一些仅在处理 ASCII 兼容数据时可用,并且在许多特性上与字符串对象紧密相关的方法。
class bytes
([source[, encoding[, errors]]])
首先,表示 bytes 字面值的语法与字符串字面值的大致相同,只是添加了一个 b
前缀:
- 单引号:
b'同样允许嵌入 "双" 引号'
。 - 双引号:
b"同样允许嵌入 '单' 引号"
。 - 三重引号:
b'''三重单引号'''
,b"""三重双引号"""
bytes 字面值中只允许 ASCII 字符(无论源代码声明的编码为何)。 任何超出 127 的二进制值必须使用相应的转义序列形式加入 bytes 字面值。
像字符串字面值一样,bytes 字面值也可以使用 r
前缀来禁用转义序列处理。
虽然 bytes 字面值和表示法是基于 ASCII 文本的,但 bytes 对象的行为实际上更像是不可变的整数序列,序列中的每个值的大小被限制为 0 <= x < 256
(如果违反此限制将引发 ValueError
)。 这种限制是有意设计用以强调以下事实,虽然许多二进制格式都包含基于 ASCII 的元素,可以通过某些面向文本的算法进行有用的操作,但情况对于任意二进制数据来说通常却并非如此(盲目地将文本处理算法应用于不兼容 ASCII 的二进制数据格式往往将导致数据损坏)。
除了字面值形式,bytes 对象还可以通过其他几种方式来创建:
- 指定长度的以零值填充的 bytes 对象:
bytes(10)
- 通过由整数组成的可迭代对象:
bytes(range(20))
- 通过缓冲区协议复制现有的二进制数据:
bytes(obj)
由于两个十六进制数码精确对应一个字节,因此十六进制数是描述二进制数据的常用格式。 相应地,bytes 类型具有从此种格式读取数据的附加类方法:
classmethod
fromhex
(string)此
bytes
类方法返回一个解码给定字符串的 bytes 对象。 字符串必须由表示每个字节的两个十六进制数码构成,其中的 ASCII 空白符会被忽略。>>> bytes.fromhex('2Ef0 F1f2 ') b'.\xf0\xf1\xf2'
在 3.7 版更改:
bytes.fromhex()
现在会忽略所有 ASCII 空白符而不只是空格符。
存在一个反向转换函数,可以将 bytes 对象转换为对应的十六进制表示。
hex
([sep[, bytes_per_sep]])返回一个字符串对象,该对象包含实例中每个字节的两个十六进制数字。
>>> b'\xf0\xf1\xf2'.hex() 'f0f1f2'
如果你希望令十六进制数字符串更易读,你可以指定单个字符分隔符作为 sep 形参包含于输出中。 默认会放在每个字节之间。 第二个可选的 bytes_per_sep 形参控制间距。 正值会从右开始计算分隔符的位置,负值则是从左开始。
>>> value = b'\xf0\xf1\xf2' >>> value.hex('-') 'f0-f1-f2' >>> value.hex('_', 2) 'f0_f1f2' >>> b'UUDDLRLRAB'.hex(' ', -4) '55554444 4c524c52 4142'
3.5 新版功能.
在 3.8 版更改:
bytes.hex()
现在支持可选的 sep 和 bytes_per_sep 形参以在十六进制输出的字节之间插入分隔符。
由于 bytes 对象是由整数构成的序列(类似于元组),因此对于一个 bytes 对象 b,b[0]
将为一个整数,而 b[0:1]
将为一个长度为 1 的 bytes 对象。 (这与文本字符串不同,索引和切片所产生的将都是一个长度为 1 的字符串)。
bytes 对象的表示使用字面值格式 (b'...'
),因为它通常都要比像 bytes([46, 46, 46])
这样的格式更好用。 你总是可以使用 list(b)
将 bytes 对象转换为一个由整数构成的列表。
注解
针对 Python 2.x 用户的说明:在 Python 2.x 系列中,允许 8 位字符串( 2.x 所提供的最接近内置二进制数据类型的对象)与 Unicode 字符串进行各种隐式转换。 这是为了实现向下兼容的变通做法,以适应 Python 最初只支持 8 位文本而 Unicode 文本是后来才被加入这一事实。 在 Python 3.x 中,这些隐式转换已被取消 —— 8 位二进制数据与 Unicode 文本间的转换必须显式地进行,bytes 与字符串对象的比较结果将总是不相等。
bytearray 对象
bytearray
对象是 bytes
对象的可变对应物。
class bytearray
([source[, encoding[, errors]]])
bytearray 对象没有专属的字面值语法,它们总是通过调用构造器来创建:
- 创建一个空实例:
bytearray()
- 创建一个指定长度的以零值填充的实例:
bytearray(10)
- 通过由整数组成的可迭代对象:
bytearray(range(20))
- 通过缓冲区协议复制现有的二进制数据:
bytearray(b'Hi!')
由于 bytearray 对象是可变的,该对象除了 bytes 和 bytearray 操作 中所描述的 bytes 和 bytearray 共有操作之外,还支持 可变 序列操作。
由于两个十六进制数码精确对应一个字节,因此十六进制数是描述二进制数据的常用格式。 相应地,bytearray 类型具有从此种格式读取数据的附加类方法:
classmethod
fromhex
(string)bytearray
类方法返回一个解码给定字符串的 bytearray 对象。 字符串必须由表示每个字节的两个十六进制数码构成,其中的 ASCII 空白符会被忽略。>>> bytearray.fromhex('2Ef0 F1f2 ') bytearray(b'.\xf0\xf1\xf2')
在 3.7 版更改:
bytearray.fromhex()
现在会忽略所有 ASCII 空白符而不只是空格符。
存在一个反向转换函数,可以将 bytearray 对象转换为对应的十六进制表示。
hex
([sep[, bytes_per_sep]])返回一个字符串对象,该对象包含实例中每个字节的两个十六进制数字。
>>> bytearray(b'\xf0\xf1\xf2').hex() 'f0f1f2'
3.5 新版功能.
在 3.8 版更改: 与
bytes.hex()
相似,bytearray.hex()
现在支持可选的 sep 和 bytes_per_sep 参数以在十六进制输出的字节之间插入分隔符。
由于 bytearray 对象是由整数构成的序列(类似于列表),因此对于一个 bytearray 对象 b,b[0]
将为一个整数,而 b[0:1]
将为一个长度为 1 的 bytearray 对象。 (这与文本字符串不同,索引和切片所产生的将都是一个长度为 1 的字符串)。
bytearray 对象的表示使用 bytes 对象字面值格式 (bytearray(b'...')
),因为它通常都要比 bytearray([46, 46, 46])
这样的格式更好用。 你总是可以使用 list(b)
将 bytearray 对象转换为一个由整数构成的列表。
bytes 和 bytearray 操作
bytes 和 bytearray 对象都支持 通用 序列操作。 它们不仅能与相同类型的操作数,也能与任何 bytes-like object 进行互操作。 由于这样的灵活性,它们可以在操作中自由地混合而不会导致错误。 但是,操作结果的返回值类型可能取决于操作数的顺序。
注解
bytes 和 bytearray 对象的方法不接受字符串作为其参数,就像字符串的方法不接受 bytes 对象作为其参数一样。 例如,你必须使用以下写法:
a = "abc"
b = a.replace("a", "f")
和:
a = b"abc"
b = a.replace(b"a", b"f")
某些 bytes 和 bytearray 操作假定使用兼容 ASCII 的二进制格式,因此在处理任意二进数数据时应当避免使用。 这些限制会在下文中说明。
注解
使用这些基于 ASCII 的操作来处理未以基于 ASCII 的格式存储的二进制数据可能会导致数据损坏。
bytes 和 bytearray 对象的下列方法可以用于任意二进制数据。
bytes.count
(sub[, start[, end]])
bytearray.count
(sub[, start[, end]])
返回子序列 sub 在 [start, end*] 范围内非重叠出现的次数。 可选参数 *start 与 end 会被解读为切片表示法。
要搜索的子序列可以是任意 bytes-like object 或是 0 至 255 范围内的整数。
在 3.3 版更改: 也接受 0 至 255 范围内的整数作为子序列。
bytes.removeprefix
(prefix, /)
bytearray.removeprefix
(prefix, /)
如果二进制数据以 前缀 字符串开头,返回 bytes[len(prefix):]
。否则,返回原始二进制数据的副本:
>>> b'TestHook'.removeprefix(b'Test')
b'Hook'
>>> b'BaseTestCase'.removeprefix(b'Test')
b'BaseTestCase'
前缀可以是任意 bytes-like object。
注解
此方法的 bytearray 版本 并非 原地操作 —— 它总是产生一个新对象,即便没有做任何改变。
3.9 新版功能.
bytes.removesuffix
(suffix, /)
bytearray.removesuffix
(suffix, /)
如果二进制数据以 后缀 字符串结尾,并且 后缀 非空,返回 bytes[:-len(suffix)]
。否则,返回原始二进制数据的副本:
>>> b'MiscTests'.removesuffix(b'Tests')
b'Misc'
>>> b'TmpDirMixin'.removesuffix(b'Tests')
b'TmpDirMixin'
后缀可以是任意 bytes-like object。
注解
此方法的 bytearray 版本 并非 原地操作 —— 它总是产生一个新对象,即便没有做任何改变。
3.9 新版功能.
bytes.decode
(encoding=’utf-8’, errors=’strict’)
bytearray.decode
(encoding=’utf-8’, errors=’strict’)
返回从给定 bytes 解码出来的字符串。 默认编码为 'utf-8'
。 可以给出 errors 来设置不同的错误处理方案。 errors 的默认值为 'strict'
,表示编码错误会引发 UnicodeError
。 其他可用的值为 'ignore'
, 'replace'
以及任何其他通过 codecs.register_error()
注册的名称。
By default, the errors argument is not checked for best performances, but only used at the first decoding error. Enable the Python Development Mode, or use a debug build to check errors.
注解
将 encoding 参数传给 str
允许直接解码任何 bytes-like object,无须创建临时的 bytes 或 bytearray 对象。
在 3.1 版更改: 加入了对关键字参数的支持。
在 3.9 版更改: The errors is now checked in development mode and in debug mode.
bytes.endswith
(suffix[, start[, end]])
bytearray.endswith
(suffix[, start[, end]])
如果二进制数据以指定的 suffix 结束则返回 True
,否则返回 False
。 suffix 也可以为由多个供查找的后缀构成的元组。 如果有可选项 start,将从所指定位置开始检查。 如果有可选项 end,将在所指定位置停止比较。
要搜索的后缀可以是任意 bytes-like object。
bytes.find
(sub[, start[, end]])
bytearray.find
(sub[, start[, end]])
返回子序列 sub 在数据中被找到的最小索引,sub 包含于切片 s[start:end]
之内。 可选参数 start 与 end 会被解读为切片表示法。 如果 sub 未被找到则返回 -1
。
要搜索的子序列可以是任意 bytes-like object 或是 0 至 255 范围内的整数。
注解
find()
方法应该只在你需要知道 sub 所在位置时使用。 要检查 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)
返回一个由 iterable 中的二进制数据序列拼接而成的 bytes 或 bytearray 对象。 如果 iterable 中存在任何非 字节类对象 包括存在 str
对象值则会引发 TypeError
。 提供该方法的 bytes 或 bytearray 对象的内容将作为元素之间的分隔。
static bytes.maketrans
(from, to)
static bytearray.maketrans
(from, to)
此静态方法返回一个可用于 bytes.translate()
的转换对照表,它将把 from 中的每个字符映射为 to 中相同位置上的字符;from 与 to 必须都是 字节类对象 并且具有相同的长度。
3.1 新版功能.
bytes.partition
(sep)
bytearray.partition
(sep)
在 sep 首次出现的位置拆分序列,返回一个 3 元组,其中包含分隔符之前的部分、分隔符本身或其 bytearray 副本,以及分隔符之后的部分。 如果分隔符未找到,则返回的 3 元组中包含原序列以及两个空的 bytes 或 bytearray 对象。
要搜索的分隔符可以是任意 bytes-like object。
bytes.replace
(old, new[, count])
bytearray.replace
(old, new[, count])
返回序列的副本,其中出现的所有子序列 old 都将被替换为 new。 如果给出了可选参数 *count,则只替换前 *count 次出现。
要搜索的子序列及其替换序列可以是任意 bytes-like object。
注解
此方法的 bytearray 版本 并非 原地操作 —— 它总是产生一个新对象,即便没有做任何改变。
bytes.rfind
(sub[, start[, end]])
bytearray.rfind
(sub[, start[, end]])
返回子序列 sub 在序列内被找到的最大(最右)索引,这样 sub 将包含在 s[start:end]
当中。 可选参数 start 与 end 会被解读为切片表示法。 如果未找到则返回 -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 元组,其中包含分隔符之前的部分,分隔符本身或其 bytearray 副本,以及分隔符之后的部分。 如果分隔符未找到,则返回的 3 元组中包含两个空的 bytes 或 bytearray 对象以及原序列的副本。
要搜索的分隔符可以是任意 bytes-like object。
bytes.startswith
(prefix[, start[, end]])
bytearray.startswith
(prefix[, start[, end]])
如果二进制数据以指定的 prefix 开头则返回 True
,否则返回 False
。 prefix 也可以为由多个供查找的前缀构成的元组。 如果有可选项 start,将从所指定位置开始检查。 如果有可选项 end,将在所指定位置停止比较。
要搜索的前缀可以是任意 bytes-like object。
bytes.translate
(table, /, delete=b’’)
bytearray.translate
(table, /, delete=b’’)
返回原 bytes 或 bytearray 对象的副本,移除其中所有在可选参数 delete 中出现的 bytes,其余 bytes 将通过给定的转换表进行映射,该转换表必须是长度为 256 的 bytes 对象。
你可以使用 bytes.maketrans()
方法来创建转换表。
对于仅需移除字符的转换,请将 table 参数设为 None
:
>>> b'read this short text'.translate(None, b'aeiou')
b'rd ths shrt txt'
在 3.6 版更改: 现在支持将 delete 作为关键字参数。
以下 bytes 和 bytearray 对象的方法的默认行为会假定使用兼容 ASCII 的二进制格式,但通过传入适当的参数仍然可用于任意二进制数据。 请注意本小节中所有的 bytearray 方法都 不是 原地执行操作,而是会产生新的对象。
bytes.center
(width[, fillbyte])
bytearray.center
(width[, fillbyte])
返回原对象的副本,在长度为 width 的序列内居中,使用指定的 fillbyte 填充两边的空位(默认使用 ASCII 空格符)。 对于 bytes
对象,如果 width 小于等于 len(s)
则返回原序列的副本。
注解
此方法的 bytearray 版本 并非 原地操作 —— 它总是产生一个新对象,即便没有做任何改变。
bytes.ljust
(width[, fillbyte])
bytearray.ljust
(width[, fillbyte])
返回原对象的副本,在长度为 width 的序列中靠左对齐。 使用指定的 fillbyte 填充空位(默认使用 ASCII 空格符)。 对于 bytes
对象,如果 width 小于等于 len(s)
则返回原序列的副本。
注解
此方法的 bytearray 版本 并非 原地操作 —— 它总是产生一个新对象,即便没有做任何改变。
bytes.lstrip
([chars])
bytearray.lstrip
([chars])
返回原序列的副本,移除指定的前导字节。 chars 参数为指定要移除字节值集合的二进制序列 —— 这个名称表明此方法通常是用于 ASCII 字符。 如果省略或为 None
,则 chars 参数默认移除 ASCII 空白符。 chars 参数并非指定单个前缀;而是会移除参数值的所有组合:
>>> b' spacious '.lstrip()
b'spacious '
>>> b'www.example.com'.lstrip(b'cmowz.')
b'example.com'
要移除的二进制序列可以是任意 bytes-like object 。 要删除单个前缀字符串,而不是全部给定集合中的字符,请参见 str.removeprefix()
方法。 例如:
>>> b'Arthur: three!'.lstrip(b'Arthur: ')
b'ee!'
>>> b'Arthur: three!'.removeprefix(b'Arthur: ')
b'three!'
注解
此方法的 bytearray 版本 并非 原地操作 —— 它总是产生一个新对象,即便没有做任何改变。
bytes.rjust
(width[, fillbyte])
bytearray.rjust
(width[, fillbyte])
返回原对象的副本,在长度为 width 的序列中靠右对齐。 使用指定的 fillbyte 填充空位(默认使用 ASCII 空格符)。 对于 bytes
对象,如果 width 小于等于 len(s)
则返回原序列的副本。
注解
此方法的 bytearray 版本 并非 原地操作 —— 它总是产生一个新对象,即便没有做任何改变。
bytes.rsplit
(sep=None, maxsplit=- 1)
bytearray.rsplit
(sep=None, maxsplit=- 1)
将二进制序列拆分为相同类型的子序列,使用 sep 作为分隔符。 如果给出了 maxsplit*,则最多进行 *maxsplit 次拆分,从 最右边 开始。 如果 sep 未指定或为 None
,任何只包含 ASCII 空白符的子序列都会被作为分隔符。 除了从右边开始拆分,rsplit()
的其他行为都类似于下文所述的 split()
。
bytes.rstrip
([chars])
bytearray.rstrip
([chars])
返回原序列的副本,移除指定的末尾字节。 chars 参数为指定要移除字节值集合的二进制序列 —— 这个名称表明此方法通常是用于 ASCII 字符。 如果省略或为 None
,则 chars 参数默认移除 ASCII 空白符。 chars 参数并非指定单个后缀;而是会移除参数值的所有组合:
>>> b' spacious '.rstrip()
b' spacious'
>>> b'mississippi'.rstrip(b'ipz')
b'mississ'
要移除的二进制序列可以是任意 bytes-like object 。 要删除单个后缀字符串,而不是全部给定集合中的字符,请参见 str.removesuffix()
方法。 例如:
>>> b'Monty Python'.rstrip(b' Python')
b'M'
>>> b'Monty Python'.removesuffix(b' Python')
b'Monty'
注解
此方法的 bytearray 版本 并非 原地操作 —— 它总是产生一个新对象,即便没有做任何改变。
bytes.split
(sep=None, maxsplit=- 1)
bytearray.split
(sep=None, maxsplit=- 1)
将二进制序列拆分为相同类型的子序列,使用 sep 作为分隔符。 如果给出了 maxsplit 且非负值,则最多进行 maxsplit 次拆分(因此,列表最多会有 maxsplit+1
个元素)。 如果 maxsplit 未指定或为 -1
,则不限制拆分次数(进行所有可能的拆分)。
如果给出了 sep*,则连续的分隔符不会被组合在一起而是被视为分隔空子序列 (例如 b'1,,2'.split(b',')
将返回 [b'1', b'', b'2']
)。 *sep 参数可能为一个多字节序列 (例如 b'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'']
如果 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'
要移除的字节值二进制序列可以是任意 bytes-like object。
注解
此方法的 bytearray 版本 并非 原地操作 —— 它总是产生一个新对象,即便没有做任何改变。
以下 bytes 和 bytearray 对象的方法会假定使用兼容 ASCII 的二进制格式,不应当被应用于任意二进制数据。 请注意本小节中所有的 bytearray 方法都 不是 原地执行操作,而是会产生新的对象。
bytes.capitalize
()
bytearray.capitalize
()
返回原序列的副本,其中每个字节将都将被解读为一个 ASCII 字符,并且第一个字节的字符大写而其余的小写。 非 ASCII 字节值将保持原样不变。
注解
此方法的 bytearray 版本 并非 原地操作 —— 它总是产生一个新对象,即便没有做任何改变。
bytes.expandtabs
(tabsize=8)
bytearray.expandtabs
(tabsize=8)
返回序列的副本,其中所有的 ASCII 制表符会由一个或多个 ASCII 空格替换,具体取决于当前列位置和给定的制表符宽度。 每 tabsize 个字节设为一个制表位(默认值 8 时设定的制表位在列 0, 8, 16 依次类推)。 要展开序列,当前列位置将被设为零并逐一检查序列中的每个字节。 如果字节为 ASCII 制表符 (b'\t'
),则并在结果中插入一个或多个空格符,直到当前列等于下一个制表位。 (制表符本身不会被复制。) 如果当前字节为 ASCII 换行符 (b'\n'
) 或回车符 (b'\r'
),它会被复制并将当前列重设为零。 任何其他字节会被不加修改地复制并将当前列加一,不论该字节值在被打印时会如何显示:
>>> b'01\t012\t0123\t01234'.expandtabs()
b'01 012 0123 01234'
>>> b'01\t012\t0123\t01234'.expandtabs(4)
b'01 012 0123 01234'
注解
此方法的 bytearray 版本 并非 原地操作 —— 它总是产生一个新对象,即便没有做任何改变。
bytes.isalnum
()
bytearray.isalnum
()
如果序列中所有字节都是字母类 ASCII 字符或 ASCII 十进制数码并且序列非空则返回 True
,否则返回 False
。 字母类 ASCII 字符就是字节值包含在序列 b'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
中的字符。 ASCII 十进制数码就是字节值包含在序列 b'0123456789'
中的字符。
例如:
>>> b'ABCabc1'.isalnum()
True
>>> b'ABC abc1'.isalnum()
False
bytes.isalpha
()
bytearray.isalpha
()
如果序列中所有字节都是字母类 ASCII 字符并且序列不非空则返回 True
,否则返回 False
。 字母类 ASCII 字符就是字节值包含在序列 b'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
中的字符。
例如:
>>> b'ABCabc'.isalpha()
True
>>> b'ABCabc1'.isalpha()
False
bytes.isascii
()
bytearray.isascii
()
如果序列为空或序列中所有字节都是 ASCII 字节则返回 True
,否则返回 False
。 ASCII 字节的取值范围是 0-0x7F。
3.7 新版功能.
bytes.isdigit
()
bytearray.isdigit
()
如果序列中所有字节都是 ASCII 十进制数码并且序列非空则返回 True
,否则返回 False
。 ASCII 十进制数码就是字节值包含在序列 b'0123456789'
中的字符。
例如:
>>> b'1234'.isdigit()
True
>>> b'1.23'.isdigit()
False
bytes.islower
()
bytearray.islower
()
如果序列中至少有一个小写的 ASCII 字符并且没有大写的 ASCII 字符则返回 True
,否则返回 False
。
例如:
>>> b'hello world'.islower()
True
>>> b'Hello world'.islower()
False
小写 ASCII 字符就是字节值包含在序列 b'abcdefghijklmnopqrstuvwxyz'
中的字符。 大写 ASCII 字符就是字节值包含在序列 b'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
中的字符。
bytes.isspace
()
bytearray.isspace
()
如果序列中所有字节都是 ASCII 空白符并且序列非空则返回 True
,否则返回 False
。 ASCII 空白符就是字节值包含在序列 b' \t\n\r\x0b\f'
(空格, 制表, 换行, 回车, 垂直制表, 进纸) 中的字符。
bytes.istitle
()
bytearray.istitle
()
如果序列为 ASCII 标题大小写形式并且序列非空则返回 True
,否则返回 False
。
例如:
>>> b'Hello World'.istitle()
True
>>> b'Hello world'.istitle()
False
bytes.isupper
()
bytearray.isupper
()
如果序列中至少有一个大写字母 ASCII 字符并且没有小写 ASCII 字符则返回 True
,否则返回 False
。
例如:
>>> b'HELLO WORLD'.isupper()
True
>>> b'Hello world'.isupper()
False
小写 ASCII 字符就是字节值包含在序列 b'abcdefghijklmnopqrstuvwxyz'
中的字符。 大写 ASCII 字符就是字节值包含在序列 b'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
中的字符。
bytes.lower
()
bytearray.lower
()
返回原序列的副本,其所有大写 ASCII 字符均转换为对应的小写形式。
例如:
>>> b'Hello World'.lower()
b'hello world'
小写 ASCII 字符就是字节值包含在序列 b'abcdefghijklmnopqrstuvwxyz'
中的字符。 大写 ASCII 字符就是字节值包含在序列 b'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
中的字符。
注解
此方法的 bytearray 版本 并非 原地操作 —— 它总是产生一个新对象,即便没有做任何改变。
bytes.splitlines
(keepends=False)
bytearray.splitlines
(keepends=False)
返回由原二进制序列中各行组成的列表,在 ASCII 行边界符的位置拆分。 此方法使用 universal newlines 方式来分行。 结果列表中不包含换行符,除非给出了 keepends 且为真值。
例如:
>>> b'ab c\n\nde fg\rkl\r\n'.splitlines()
[b'ab c', b'', b'de fg', b'kl']
>>> b'ab c\n\nde fg\rkl\r\n'.splitlines(keepends=True)
[b'ab c\n', b'\n', b'de fg\r', b'kl\r\n']
不同于 split()
,当给出了分隔符 sep 时,对于空字符串此方法将返回一个空列表,而末尾的换行不会令结果中增加额外的行:
>>> b"".split(b'\n'), b"Two lines\n".split(b'\n')
([b''], [b'Two lines', b''])
>>> b"".splitlines(), b"One line\n".splitlines()
([], [b'One line'])
bytes.swapcase
()
bytearray.swapcase
()
返回原序列的副本,其所有小写 ASCII 字符均转换为对应的大写形式,反之亦反。
例如:
>>> b'Hello World'.swapcase()
b'hELLO wORLD'
小写 ASCII 字符就是字节值包含在序列 b'abcdefghijklmnopqrstuvwxyz'
中的字符。 大写 ASCII 字符就是字节值包含在序列 b'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
中的字符。
不同于 str.swapcase()
,在些二进制版本下 bin.swapcase().swapcase() == bin
总是成立。 大小写转换在 ASCII 中是对称的,即使其对于任意 Unicode 码位来说并不总是成立。
注解
此方法的 bytearray 版本 并非 原地操作 —— 它总是产生一个新对象,即便没有做任何改变。
bytes.title
()
bytearray.title
()
返回原二进制序列的标题版本,其中每个单词以一个大写 ASCII 字符为开头,其余字母为小写。 不区别大小写的字节值将保持原样不变。
例如:
>>> b'Hello world'.title()
b'Hello World'
小写 ASCII 字符就是字节值包含在序列 b'abcdefghijklmnopqrstuvwxyz'
中的字符。 大写 ASCII 字符就是字节值包含在序列 b'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
中的字符。 所有其他字节值都不区分大小写。
该算法使用一种简单的与语言无关的定义,将连续的字母组合视为单词。 该定义在多数情况下都很有效,但它也意味着代表缩写形式与所有格的撇号也会成为单词边界,这可能导致不希望的结果:
>>> b"they're bill's friends from the UK".title()
b"They'Re Bill'S Friends From The Uk"
可以使用正则表达式来构建针对撇号的特别处理:
>>> import re
>>> def titlecase(s):
... return re.sub(rb"[A-Za-z]+('[A-Za-z]+)?",
... lambda mo: mo.group(0)[0:1].upper() +
... mo.group(0)[1:].lower(),
... s)
...
>>> titlecase(b"they're bill's friends.")
b"They're Bill's Friends."
注解
此方法的 bytearray 版本 并非 原地操作 —— 它总是产生一个新对象,即便没有做任何改变。
bytes.upper
()
bytearray.upper
()
返回原序列的副本,其所有小写 ASCII 字符均转换为对应的大写形式。
例如:
>>> b'Hello World'.upper()
b'HELLO WORLD'
小写 ASCII 字符就是字节值包含在序列 b'abcdefghijklmnopqrstuvwxyz'
中的字符。 大写 ASCII 字符就是字节值包含在序列 b'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
中的字符。
注解
此方法的 bytearray 版本 并非 原地操作 —— 它总是产生一个新对象,即便没有做任何改变。
bytes.zfill
(width)
bytearray.zfill
(width)
返回原序列的副本,在左边填充 b'0'
数码使序列长度为 width*。 正负值前缀 (b'+'
/ b'-'
) 的处理方式是在正负符号 *之后 填充而非在之前。 对于 bytes
对象,如果 width 小于等于 len(seq)
则返回原序列。
例如:
>>> b"42".zfill(5)
b'00042'
>>> b"-42".zfill(5)
b'-0042'
注解
此方法的 bytearray 版本 并非 原地操作 —— 它总是产生一个新对象,即便没有做任何改变。
printf
风格的字节串格式化
注解
此处介绍的格式化操作具有多种怪异特性,可能导致许多常见错误(例如无法正确显示元组和字典)。 如果要打印的值可能为元组或字典,请将其放入一个元组中。
字节串对象 (bytes
/bytearray
) 具有一种特殊的内置操作:使用 %
(取模) 运算符。 这也被称为字节串的 格式化 或 插值 运算符。 对于 format % values
(其中 format 为一个字节串对象),在 format 中的 %
转换标记符将被替换为零个或多个 values 条目。 其效果类似于在 C 语言中使用 sprintf()
。
如果 format 要求一个单独参数,则 values 可以为一个非元组对象。否则的话,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.'
在此情况下格式中不能出现 *
标记符(因其需要一个序列类的参数列表)。
转换旗标为:
旗标 | 含意 |
---|---|
‘#’ |
值的转换将使用“替代形式”(具体定义见下文)。 |
‘0’ |
转换将为数字值填充零字符。 |
‘-‘ |
转换值将靠左对齐(如果同时给出 ‘0’ 转换,则会覆盖后者)。 |
‘ ‘ |
(空格) 符号位转换产生的正数(或空字符串)前将留出一个空格。 |
‘+’ |
符号字符 (‘+’ 或 ‘-‘ ) 将显示于转换结果的开头(会覆盖 “空格” 旗标)。 |
可以给出长度修饰符 (h
, l
或 L
),但会被忽略,因为对 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) |
‘%’ |
不转换参数,在结果中输出一个 ‘%’ 字符。 |
注释:
此替代形式会在第一个数码之前插入标示八进制数的前缀 (
'0o'
)。此替代形式会在第一个数码之前插入
'0x'
或'0X'
前缀(取决于是使用'x'
还是'X'
格式)。此替代形式总是会在结果中包含一个小数点,即使其后并没有数码。
小数点后的数码位数由精度决定,默认为 6。
此替代形式总是会在结果中包含一个小数点,末尾各位的零不会如其他情况下那样被移除。
小数点前后的有效数码位数由精度决定,默认为 6。
如果精度为
N
,输出将截短为N
个字符。b'%s'
已弃用,但在 3.x 系列中将不会被移除。b'%r'
已弃用,但在 3.x 系列中将不会被移除。参见 PEP 237。
注解
此方法的 bytearray 版本 并非 原地操作 —— 它总是产生一个新对象,即便没有做任何改变。
参见
PEP 461 - 为 bytes 和 bytearray 添加 % 格式化
3.5 新版功能.
内存视图
memoryview
对象允许 Python 代码访问一个对象的内部数据,只要该对象支持 缓冲区协议 而无需进行拷贝。
class memoryview
(object)
创建一个引用 object 的 memoryview
。 object 必须支持缓冲区协议。支持缓冲区协议的内置对象有 bytes
和 bytearray
。
memoryview
有 元素 的概念, 元素 指由原始 object 处理的原子内存单元。对于许多简单的类型,如 bytes
和 bytearray
,一个元素是一个字节,但其他类型,如 array.array
可能有更大的元素。
len(view)
与 tolist
的长度相等。 如果 view.ndim = 0
,则其长度为 1。 如果 view.ndim = 1
,则其长度等于 view 中元素的数量。 对于更高的维度,其长度等于表示 view 的嵌套列表的长度。 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 版更改: 内存视图现在会自动注册为 collections.abc.Sequence
在 3.5 版更改: 内存视图现在可使用整数元组进行索引。
memoryview
具有以下一些方法:
__eq__
(exporter)memoryview 与 PEP 3118 中的导出器这两者如果形状相同,并且如果当使用
struct
语法解读操作数的相应格式代码时所有对应值都相同,则它们就是等价的。对于
tolist()
当前所支持的struct
格式字符串子集,如果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
也 并不 意味着v == w
。在 3.3 版更改: 之前的版本比较原始内存时会忽略条目的格式与逻辑数组结构。
tobytes
(order=None)将缓冲区中的数据作为字节串返回。 这相当于在内存视图上调用
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]
在 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
()释放由内存视图对象所公开的底层缓冲区。 许多对象在被视图所获取时都会采取特殊动作(例如,
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])将内存视图转化为新的格式或形状。 shape 默认为
[byte_length//new_itemsize]
,这意味着结果视图将是一维的。 返回值是一个新的内存视图,但缓冲区本身不会被复制。 支持的转化有 1D -> C-contiguous 和 C-contiguous -> 1D。目标格式仅限于
struct
语法中的单一元素原生格式。 其中一种格式必须为字节格式 (‘B’, ‘b’ 或 ‘c’)。 结果的字节长度必须与原始长度相同。将 1D/long 转换为 1D/unsigned bytes:
>>> import array >>> a = array.array('l', [1,2,3]) >>> x = memoryview(a) >>> x.format 'l' >>> x.itemsize 8 >>> len(x) 3 >>> x.nbytes 24 >>> y = x.cast('B') >>> y.format 'B' >>> y.itemsize 1 >>> len(y) 24 >>> y.nbytes 24
将 1D/unsigned bytes 转换为 1D/char:
>>> b = bytearray(b'zyz') >>> x = memoryview(b) >>> x[0] = b'a' Traceback (most recent call last): 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
内存视图的下层对象:
>>> 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-contiguous 的布尔值。
3.3 新版功能.
f_contiguous
一个表明内存是否为 Fortran contiguous 的布尔值。
3.3 新版功能.
contiguous
一个表明内存是否为 contiguous 的布尔值。
3.3 新版功能.
集合类型 —- set
, frozenset
set 对象是由具有唯一性的 hashable 对象所组成的无序多项集。 常见的用途包括成员检测、从序列中去除重复项以及数学中的集合类计算,例如交集、并集、差集与对称差集等等。
与其他多项集一样,集合也支持 x in set
, len(set)
和 for x in set
。 作为一种无序的多项集,集合并不记录元素位置或插入顺序。 相应地,集合不支持索引、切片或其他序列类的操作。
目前有两种内置集合类型,set
和 frozenset
。 set
类型是可变的 —- 其内容可以使用 add()
和 remove()
这样的方法来改变。 由于是可变类型,它没有哈希值,且不能被用作字典的键或其他集合的元素。 frozenset
类型是不可变并且为 hashable —- 其内容在被创建后不能再改变;因此它可以被用作字典的键或其他集合的元素。
除了可以使用 set
构造器,非空的 set (不是 frozenset) 还可以通过将以逗号分隔的元素列表包含于花括号之内来创建,例如: {'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'])
set
和 frozenset
的实例提供以下操作:
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 | ...
返回一个新集合,其中包含来自原集合以及 others 指定的所有集合中的元素。
intersection
(\others*)set & other & ...
返回一个新集合,其中包含原集合以及 others 指定的所有集合中共有的元素。
difference
(\others*)set - other - ...
返回一个新集合,其中包含原集合中在 others 指定的其他集合中不存在的元素。
symmetric_difference
(other)set ^ other
返回一个新集合,其中的元素或属于原集合或属于 other 指定的其他集合,但不能同时属于两者。
copy
()返回原集合的浅拷贝。
Note, the non-operator versions of union()
, intersection()
, difference()
, symmetric_difference()
, issubset()
, and issuperset()
methods will accept any iterable as an argument. In contrast, their operator based counterparts require their arguments to be sets. This precludes error-prone constructions like set('abc') & 'cbs'
in favor of the more readable set('abc').intersection('cbs')
.
set
和 frozenset
均支持集合与集合的比较。 两个集合当且仅当每个集合中的每个元素均包含于另一个集合之内(即各为对方的子集)时则相等。 一个集合当且仅当其为另一个集合的真子集(即为后者的子集但两者不相等)时则小于另一个集合。 一个集合当且仅当其为另一个集合的真超集(即为后者的超集但两者不相等)时则大于另一个集合。
set
的实例与 frozenset
的实例之间基于它们的成员进行比较。 例如 set('abc') == frozenset('abc')
返回 True
,set('abc') in set([frozenset('abc')])
也一样。
子集与相等比较并不能推广为完全排序函数。 例如,任意两个非空且不相交的集合不相等且互不为对方的子集,因此以下 所有 比较均返回 False
: a<b
, a==b
, or a>b
。
由于集合仅定义了部分排序(子集关系),因此由集合构成的列表 list.sort()
方法的输出并无定义。
集合的元素,与字典的键类似,必须为 hashable。
混合了 set
实例与 frozenset
的二进制位运算将返回与第一个操作数相同的类型。例如: frozenset('ab') | set('bc')
将返回 frozenset
的实例。
下表列出了可用于 set
而不能用于不可变的 frozenset
实例的操作:
update
(\others*)set |= other | ...
更新集合,添加来自 others 中的所有元素。
intersection_update
(\others*)set &= other & ...
更新集合,只保留其中在所有 others 中也存在的元素。
difference_update
(\others*)set -= other | ...
更新集合,移除其中也存在于 others 中的元素。
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 参数可能是一个 set。 为支持对一个等价的 frozenset 进行搜索,会根据 elem 临时创建一个该类型对象。
映射类型 —- dict
mapping 对象会将 hashable 值映射到任意对象。 映射属于可变对象。 目前仅有一种标准映射类型 字典。
字典的键 几乎 可以是任何值。 非 hashable 的值,即包含列表、字典或其他可变类型的值(此类对象基于值而非对象标识进行比较)不可用作键。 数字类型用作键时遵循数字比较的一般规则:如果两个数值相等 (例如 1
和 1.0
) 则两者可以被用来索引同一字典条目。 (但是请注意,由于计算机对于浮点数存储的只是近似值,因此将其用作字典键是不明智的。)
字典可以通过将以逗号分隔的 键: 值
对列表包含于花括号之内来创建,例如: {'jack': 4098, 'sjoerd': 4127}
或 {4098: 'jack', 4127: 'sjoerd'}
,也可以通过 dict
构造器来创建。
class dict
(**kwarg)
class dict
(mapping, **kwarg)
class dict
(iterable, **kwarg)
返回一个新的字典,基于可选的位置参数和可能为空的关键字参数集来初始化。
字典可用多种方式来创建:
- 使用花括号内以逗号分隔
键: 值
对的方式:{'jack': 4098, 'sjoerd': 4127}
or{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 为键的项。 如果映射中不存在 key 则会引发
KeyError
。如果字典的子类定义了方法
__missing__()
并且 key 不存在,则d[key]
操作将调用该方法并附带键 key 作为参数。d[key]
随后将返回或引发__missing__(key)
调用所返回或引发的任何对象或异常。 没有其他操作或方法会发起调用__missing__()
。 如果未定义__missing__()
,则会引发KeyError
。__missing__()
必须是一个方法;它不能是一个实例变量:>>> class Counter(dict): ... def __missing__(self, key): ... return 0 >>> c = Counter() >>> c['red'] 0 >>> c['red'] += 1 >>> c['red'] 1
上面的例子显示了
collections.Counter
实现的部分代码。 还有另一个不同的__missing__
方法是由collections.defaultdict
所使用的。d[key] = value
将
d[key]
设为 value。del d[key]
将
d[key]
从 d 中移除。 如果映射中不存在 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 成为一个可变对象例如空列表通常是没有意义的。 要获取不同的值,请改用 字典推导式。get
(key[, default])如果 key 存在于字典中则返回 key 的值,否则返回 default*。 如果 *default 未给出则默认为
None
,因而此方法绝不会引发KeyError
。items
()返回由字典项 (
(键, 值)
对) 组成的一个新视图。keys
()返回由字典键组成的一个新视图。
pop
(key[, default])如果 key 存在于字典中则将其移除并返回其值,否则返回 default*。 如果 *default 未给出且 key 不存在于字典中,则会引发
KeyError
。popitem
()从字典中移除并返回一个
(键, 值)
对。 键值对会按 LIFO 的顺序被返回。popitem()
适用于对字典进行消耗性的迭代,这在集合算法中经常被使用。 如果字典为空,调用popitem()
将引发KeyError
。在 3.7 版更改: 现在会确保采用 LIFO 顺序。 在之前的版本中,
popitem()
会返回一个任意的键/值对。reversed(d)
返回一个逆序获取字典键的迭代器。 这是
reversed(d.keys())
的快捷方式。3.8 新版功能.
setdefault
(key[, default])如果字典存在键 key ,返回它的值。如果不存在,插入值为 default 的键 key ,并返回 default 。 default 默认为
None
。update
([other])使用来自 other 的键/值对更新字典,覆盖原有的键。 返回
None
。update()
接受另一个字典对象,或者一个包含键/值对(以长度为二的元组或其他可迭代对象表示)的可迭代对象。 如果给出了关键字参数,则会以其所指定的键/值对更新字典:d.update(red=1, blue=2)
。values
()返回由字典值组成的一个新视图。
两个
dict.values()
视图之间的相等性比较将总是返回False
。 这在dict.values()
与其自身比较时也同样适用:>>> d = {'a': 1} >>> d.values() == d.values() False
d | other
合并 d 和 other 中的键和值来创建一个新的字典,两者必须都是字典。当 d 和 other 有相同键时, other 的值优先。
3.9 新版功能.
d |= other
用 other 的键和值更新字典 d ,other 可以是 mapping 或 iterable 的键值对。当 d 和 other 有相同键时, other 的值优先。
3.9 新版功能.
两个字典的比较当且仅当它们具有相同的 (键, 值)
对时才会相等(不考虑顺序)。 排序比较 (‘<’, ‘<=’, ‘>=’, ‘>’) 会引发 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 版更改: 字典现在是可逆的。
字典视图对象
由 dict.keys()
, dict.values()
和 dict.items()
所返回的对象是 视图对象。 该对象提供字典条目的一个动态视图,这意味着当字典改变时,视图也会相应改变。
字典视图可以被迭代以产生与其对应的数据,并支持成员检测:
len(dictview)
返回字典中的条目数。
iter(dictview)
返回字典中的键、值或项(以 (键, 值)
为元素的元组表示)的迭代器。
键和值是按插入时的顺序进行迭代的。 这样就允许使用 zip()
来创建 (值, 键)
对: pairs = zip(d.values(), d.keys())
。 另一个创建相同列表的方式是 pairs = [(v, k) for (k, v) in d.items()]
.
在添加或删除字典中的条目期间对视图进行迭代可能引发 RuntimeError
或者无法完全迭代所有条目。
在 3.7 版更改: 字典顺序会确保为插入顺序。
x in dictview
如果 x 是对应字典中存在的键、值或项(在最后一种情况下 x 应为一个 (键, 值)
元组) 则返回 True
。
reversed(dictview)
返回一个逆序获取字典键、值或项的迭代器。 视图将按与插入时相反的顺序进行迭代。
在 3.8 版更改: 字典视图现在是可逆的。
dictview.mapping
Return a types.MappingProxyType
that wraps the original dictionary to which the view refers.
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'}
>>> # 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
子句中的标识符。
一个返回其自身的上下文管理器的例子是 file object。 文件对象会从 enter() 返回其自身,以允许 open()
被用作 with
语句中的上下文表达式。
一个返回关联对象的上下文管理器的例子是 decimal.localcontext()
所返回的对象。 此种管理器会将活动的 decimal 上下文设为原始 decimal 上下文的一个副本并返回该副本。 这允许对 with
语句的语句体中的当前 decimal 上下文进行更改,而不会影响 with
语句以外的代码。
contextmanager.__exit__
(exc_type, exc_val, exc_tb)
退出运行时上下文并返回一个布尔值旗标来表明所发生的任何异常是否应当被屏蔽。 如果在执行 with
语句的语句体期间发生了异常,则参数会包含异常的类型、值以及回溯信息。 在其他情况下三个参数均为 None
。
自此方法返回一个真值将导致 with
语句屏蔽异常并继续执行紧随在 with
语句之后的语句。 否则异常将在此方法结束执行后继续传播。 在此方法执行期间发生的异常将会取代 with
语句的语句体中发生的任何异常。
传入的异常绝对不应当被显式地重新引发 —— 相反地,此方法应当返回一个假值以表明方法已成功完成并且不希望屏蔽被引发的异常。 这允许上下文管理代码方便地检测 __exit__()
方法是否确实已失败。
Python 定义了一些上下文管理器来支持简易的线程同步、文件或其他对象的快速关闭,以及更方便地操作活动的十进制算术上下文。 除了实现上下文管理协议以外,不同类型不会被特殊处理。
Python 的 generator 和 contextlib.contextmanager
装饰器提供了实现这些协议的便捷方式。 如果使用 contextlib.contextmanager
装饰器来装饰一个生成器函数,它将返回一个实现了必要的 __enter__()
and __exit__()
方法的上下文管理器,而不再是由未经装饰的生成器函数所产生的迭代器。
请注意,Python/C API 中 Python 对象的类型结构中并没有针对这些方法的专门槽位。 想要定义这些方法的扩展类型必须将它们作为普通的 Python 可访问方法来提供。 与设置运行时上下文的开销相比,单个类字典查找的开销可以忽略不计。
Type Annotation Types —- Generic Alias, Union
The core built-in types for type annotations are Generic Alias and Union.
Generic Alias Type
GenericAlias
objects are created by subscripting a class (usually a container), such as list[int]
. They are intended primarily for type annotations.
Usually, the subscription of container objects calls the method __getitem__()
of the object. However, the subscription of some containers’ classes may call the classmethod __class_getitem__()
of the class instead. The classmethod __class_getitem__()
should return a GenericAlias
object.
注解
If the __getitem__()
of the class’ metaclass is present, it will take precedence over the __class_getitem__()
defined in the class (see PEP 560 for more details).
The GenericAlias
object acts as a proxy for generic types, implementing parameterized generics - a specific instance of a generic which provides the types for container elements.
The user-exposed type for the GenericAlias
object can be accessed from types.GenericAlias
and used for isinstance()
checks. It can also be used to create GenericAlias
objects directly.
T[X, Y, ...]
Creates a GenericAlias
representing a type T
containing elements of types X, Y, and more depending on the T
used. For example, a function expecting a list
containing float
elements:
def average(values: list[float]) -> float:
return sum(values) / len(values)
Another example for mapping objects, using a dict
, which is a generic type expecting two type parameters representing the key type and the value type. In this example, the function expects a dict
with keys of type str
and values of type int
:
def send_post_request(url: str, body: dict[str, int]) -> None:
...
The builtin functions isinstance()
and issubclass()
do not accept GenericAlias
types for their second argument:
>>> 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
The Python runtime does not enforce type annotations. This extends to generic types and their type parameters. When creating an object from a GenericAlias
, container elements are not checked against their type. For example, the following code is discouraged, but will run without errors:
>>> t = list[str]
>>> t([1, 2, 3])
[1, 2, 3]
Furthermore, parameterized generics erase type parameters during object creation:
>>> t = list[str]
>>> type(t)
<class 'types.GenericAlias'>
>>> l = t()
>>> type(l)
<class 'list'>
Calling repr()
or str()
on a generic shows the parameterized type:
>>> repr(list[int])
'list[int]'
>>> str(list[int])
'list[int]'
The __getitem__()
method of generics will raise an exception to disallow mistakes like 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]
However, such expressions are valid when type variables are used. The index must have as many elements as there are type variable items in the GenericAlias
object’s __args__
.
>>> from typing import TypeVar
>>> Y = TypeVar('Y')
>>> dict[str, Y][int]
dict[str, int]
Standard Generic Collections
These standard library collections support parameterized generics.
tuple
list
dict
set
frozenset
type
collections.deque
collections.defaultdict
collections.OrderedDict
collections.Counter
collections.ChainMap
collections.abc.Awaitable
collections.abc.Coroutine
collections.abc.AsyncIterable
collections.abc.AsyncIterator
collections.abc.AsyncGenerator
collections.abc.Iterable
collections.abc.Iterator
collections.abc.Generator
collections.abc.Reversible
collections.abc.Container
collections.abc.Collection
collections.abc.Callable
collections.abc.Set
collections.abc.MutableSet
collections.abc.Mapping
collections.abc.MutableMapping
collections.abc.Sequence
collections.abc.MutableSequence
collections.abc.ByteString
collections.abc.MappingView
collections.abc.KeysView
collections.abc.ItemsView
collections.abc.ValuesView
contextlib.AbstractContextManager
contextlib.AbstractAsyncContextManager
- re.Pattern
- re.Match
Special Attributes of Generic Alias
All parameterized generics implement special read-only attributes.
genericalias.__origin__
This attribute points at the non-parameterized generic class:
>>> list[int].__origin__
<class 'list'>
genericalias.__args__
This attribute is a tuple
(possibly of length 1) of generic types passed to the original __class_getitem__()
of the generic container:
>>> dict[str, list[int]].__args__
(<class 'str'>, list[int])
genericalias.__parameters__
This attribute is a lazily computed tuple (possibly empty) of unique type variables found in __args__
:
>>> from typing import TypeVar
>>> T = TypeVar('T')
>>> list[T].__parameters__
(~T,)
注解
A GenericAlias
object with typing.ParamSpec
parameters may not have correct __parameters__
after substitution because typing.ParamSpec
is intended primarily for static type checking.
参见
- PEP 585 — “Type Hinting Generics In Standard Collections”
__class_getitem__()
— Used to implement parameterized generics.- 泛型(Generic) — Generics in the
typing
module.
3.9 新版功能.
Union Type
A union object holds the value of the |
(bitwise or) operation on multiple type objects. These types are intended primarily for type annotations. The union type expression enables cleaner type hinting syntax compared to typing.Union
.
X | Y | ...
Defines a union object which holds types X, Y, and so forth. X | Y
means either X or Y. It is equivalent to typing.Union[X, Y]
. For example, the following function expects an argument of type int
or float
:
def square(number: int | float) -> int | float:
return number ** 2
union_object == other
Union objects can be tested for equality with other union objects. Details:
Unions of unions are flattened:
(int | str) | float == int | str | float
Redundant types are removed:
int | str | int == int | str
When comparing unions, the order is ignored:
int | str == str | int
It is compatible with
typing.Union
:int | str == typing.Union[int, str]
Optional types can be spelled as a union with
None
:str | None == typing.Optional[str]
isinstance(obj, union_object)
issubclass(obj, union_object)
Calls to isinstance()
and issubclass()
are also supported with a union object:
>>> isinstance("", int | str)
True
However, union objects containing parameterized generics cannot be used:
>>> 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
The user-exposed type for the union object can be accessed from types.UnionType
and used for isinstance()
checks. An object cannot be instantiated from the type:
>>> 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
注解
The __or__()
method for type objects was added to support the syntax X | Y
. If a metaclass implements __or__()
, the Union may override it:
>>> 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 proposing the X | Y
syntax and the Union type.
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)
。
与函数对象类似,绑定方法对象也支持获取任意属性。 但是,由于方法属性实际上保存于下层的函数对象中 (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__
属性从中提取。
Accessing __code__
raises an auditing event object.__getattr__
with arguments obj
and "__code__"
.
可以通过将代码对象(而非源码字符串)传给 exec()
或 eval()
内置函数来执行或求值。
类型对象
类型对象表示各种对象类型。 对象的类型可通过内置函数 type()
来获取。 类型没有特殊的操作。 标准库模块 types
定义了所有标准内置类型的名称。
类型以这样的写法来表示: <class 'int'>
。
空对象
此对象会由不显式地返回值的函数所返回。 它不支持任何特殊的操作。 空对象只有一种值 None
(这是个内置名称)。 type(None)()
会生成同一个单例。
该对象的写法为 None
。
省略符对象
此对象常被用于切片。 它不支持任何特殊的操作。 省略符对象只有一种值 Ellipsis
(这是个内置名称)。 type(Ellipsis)()
会生成 Ellipsis
单例。
该对象的写法为 Ellipsis
或 ...
。
未实现对象
此对象会被作为比较和二元运算被应用于它们所不支持的类型时的返回值。未实现对象只有一种值 NotImplemented
。 type(NotImplemented)()
会生成这个单例。
该对象的写法为 NotImplemented
。
布尔值
布尔值是两个常量对象 False
和 True
。 它们被用来表示逻辑上的真假(不过其他值也可被当作真值或假值)。 在数字类的上下文中(例如被用作算术运算符的参数时),它们的行为分别类似于整数 0 和 1。 内置函数 bool()
可被用来将任意值转换为布尔值,只要该值可被解析为一个逻辑值。
该对象的写法分别为 False
和 True
。
内部对象
有关此对象的信息请参阅 标准类型层级结构。 其中描述了栈帧对象、回溯对象以及切片对象等等。
特殊属性
语言实现为部分对象类型添加了一些特殊的只读属性,它们具有各自的作用。 其中一些并不会被 dir()
内置函数所列出。
object.__dict__
一个字典或其他类型的映射对象,用于存储对象的(可写)属性。
instance.__class__
类实例所属的类。
class.__bases__
由类对象的基类所组成的元组。
definition.__name__
类、函数、方法、描述器或生成器实例的名称。
definition.__qualname__
类、函数、方法、描述器或生成器实例的 qualified name。
3.3 新版功能.
class.__mro__
此属性是由类组成的元组,在方法解析期间会基于它来查找基类。
class.mro
()
此方法可被一个元类来重载,以为其实例定制方法解析顺序。 它会在类实例化时被调用,其结果存储于 __mro__
之中。
class.__subclasses__
()
Each class keeps a list of weak references to its immediate subclasses. This method returns a list of all those references still alive. The list is in definition order. Example:
>>> int.__subclasses__()
[<class 'bool'>]
内置异常
在 Python 中,所有异常必须为一个派生自 BaseException
的类的实例。 在带有提及一个特定类的 except
子句的 try
语句中,该子句也会处理任何派生自该类的异常类(但不处理 它 所派生出的异常类)。 通过子类化创建的两个不相关异常类永远是不等效的,既使它们具有相同的名称。
下面列出的内置异常可通过解释器或内置函数来生成。除非另有说明,它们都会具有一个提示导致错误详细原因的“关联值”。 这可以是一个字符串或由多个信息项(例如一个错误码和一个解释错误的字符串)组成的元组。 关联值通常会作为参数被传递给异常类的构造器。
用户代码可以引发内置异常。 这可被用于测试异常处理程序或报告错误条件,“就像” 在解释器引发了相同异常的情况时一样;但是请注意,没有任何机制能防止用户代码引发不适当的错误。
内置异常类可以被子类化以定义新的异常;鼓励程序员从 Exception
类或它的某个子类而不是从 BaseException
来派生新的异常。
当在 except
或 finally
子句中引发(或重新引发)异常时,__context__
会被自动设为所捕获的最后一个异常;如果新的异常未被处理,则最终显示的回溯信息将包括原始的异常和最后的异常。
当引发一个新的异常(而不是简单地使用 raise
来重新引发 当前在处理的异常)时,隐式的异常上下文可以通过使用带有 raise
的 from
子句来补充一个显式的原因:
raise new_exc from original_exc
跟在 from
之后一表达式必须为一个异常或 None
。 它将在所引发的异常上被设置为 __cause__
。 设置 __cause__
还会隐式地将 __suppress_context__
属性设为 True
,这样使用 raise new_exc from None
可以有效地将旧异常替换为新异常来显示其目的 (例如将 KeyError
转换为 AttributeError
),同时让旧异常在 __context__
中保持可用状态以便在调试时进行内省。
除了异常本身的回溯以外,默认的回溯还会显示这些串连的异常。 __cause__
中的显式串连异常如果存在将总是显示。 __context__
中的隐式串连异常仅在 __cause__
为 None
并且 __suppress_context__
为假值时显示。
不论在哪种情况下,异常本身总会在任何串连异常之后显示,以便回溯的最后一行总是显示所引发的最后一个异常。
基类
下列异常主要被用作其他异常的基类。
- exception
BaseException
所有内置异常的基类。 它不应该被用户自定义类直接继承 (这种情况请使用 Exception
)。 如果在此类的实例上调用 str()
,则会返回实例的参数表示,或者当没有参数时返回空字符串。
args
传给异常构造器的参数元组。 某些内置异常 (例如 OSError
) 接受特定数量的参数并赋予此元组中的元素特殊的含义,而其他异常通常只接受一个给出错误信息的单独字符串。
with_traceback
(tb)
此方法会将 tb 设为新的异常回溯信息并返回异常对象。 它在 PEP 3134 的异常链特性可用之前更为常用。 下面的例子演示了我们如何将一个 SomeException
实例转换为 OtherException
实例而保留回溯信息。 异常一旦被引发,当前帧会被推至 OtherException
的回溯栈顶端,就像当我们允许原始 SomeException
被传播给调用方时它的回溯栈将会发生的情形一样。:
try:
...
except SomeException:
tb = sys.exc_info()[2]
raise OtherException(...).with_traceback(tb)
- exception
Exception
所有内置的非系统退出类异常都派生自此类。 所有用户自定义异常也应当派生自此类。
- exception
ArithmeticError
此基类用于派生针对各种算术类错误而引发的内置异常: OverflowError
, ZeroDivisionError
, FloatingPointError
。
- exception
BufferError
当与 缓冲区 相关的操作无法执行时将被引发。
- exception
LookupError
此基类用于派生当映射或序列所使用的键或索引无效时引发的异常: IndexError
, KeyError
。 这可以通过 codecs.lookup()
来直接引发。
具体异常
以下异常属于经常被引发的异常。
- exception
AssertionError
当 assert
语句失败时将被引发。
- exception
AttributeError
当属性引用 或赋值失败时将被引发。 (当一个对象根本不支持属性引用或属性赋值时则将引发 TypeError
。)
name
和 obj
属性可以使用构造器的仅限关键字参数来设置。 它们如果被设置则分别代表要尝试访问的属性名称以及所访问的该属性的对象。
在 3.10 版更改: 增加了 name
和 obj
属性。
- exception
EOFError
当 input()
函数未读取任何数据即达到文件结束条件 (EOF) 时将被引发。 (另外,io.IOBase.read()
和 io.IOBase.readline()
方法在遇到 EOF 则将返回一个空字符串。)
- exception
FloatingPointError
目前未被使用。
- exception
GeneratorExit
当一个 generator 或 coroutine 被关闭时将被引发;见 generator.close()
和 coroutine.close()
。 它直接继承自 BaseException
而不是 Exception
,因为从技术上来说它并不是一个错误。
- exception
ImportError
当 import
语句尝试加载模块遇到麻烦时将被引发。 并且当 from ... import
中的 “from list” 存在无法找到的名称时也会被引发。
name
与 path
属性可通过对构造器使用仅关键字参数来设定。 设定后它们将分别表示被尝试导入的模块名称与触发异常的任意文件所在路径。
在 3.3 版更改: 添加了 name
与 path
属性。
- exception
ModuleNotFoundError
ImportError
的子类,当一个模块无法被定位时将由 import
引发。 当在 sys.modules
中找到 None
时也会被引发。
3.6 新版功能.
- exception
IndexError
当序列抽取超出范围时将被引发。 (切片索引会被静默截短到允许的范围;如果指定索引不是整数则 TypeError
会被引发。)
- exception
KeyError
当在现有键集合中找不到指定的映射(字典)键时将被引发。
- exception
KeyboardInterrupt
当用户按下中断键 (通常为 Control-C 或 Delete) 时将被引发。 在执行期间,会定期检测中断信号。 该异常继承自 BaseException
以确保不会被处理 Exception
的代码意外捕获,这样可以避免退出解释器。
- exception
MemoryError
当一个操作耗尽内存但情况仍可(通过删除一些对象)进行挽救时将被引发。 关联的值是一个字符串,指明是哪种(内部)操作耗尽了内存。 请注意由于底层的内存管理架构(C 的 malloc()
函数),解释器也许并不总是能够从这种情况下完全恢复;但它毕竟可以引发一个异常,这样就能打印出栈回溯信息,以便找出导致问题的失控程序。
- exception
NameError
当某个局部或全局名称未找到时将被引发。 此异常仅用于非限定名称。 关联的值是一条错误信息,其中包含未找到的名称。
name
属性可以使用构造器的仅限关键字参数来设置。 它如果被设置则代表要尝试访问的变量名称。
在 3.10 版更改: 增加了 name
属性。
- exception
NotImplementedError
此异常派生自 RuntimeError
。 在用户自定义的基类中,抽象方法应当在其要求所派生类重载该方法,或是在其要求所开发的类提示具体实现尚待添加时引发此异常。
注解
它不应当用来表示一个运算符或方法根本不能被支持 — 在此情况下应当让特定运算符 / 方法保持未定义,或者在子类中将其设为 None
。
注解
NotImplementedError
和 NotImplemented
不可互换,即使它们有相似的名称和用途。
exception
OSError
([arg])exception
OSError
(errno, strerror[, filename[, winerror[, filename2]]])此异常在一个系统函数返回系统相关的错误时将被引发,此类错误包括 I/O 操作失败例如 “文件未找到” 或 “磁盘已满” 等(不包括非法参数类型或其他偶然性错误)。
构造器的第二种形式可设置如下所述的相应属性。 如果未指定这些属性则默认为
None
。 为了能向下兼容,如果传入了三个参数,则args
属性将仅包含由前两个构造器参数组成的 2 元组。构造器实际返回的往往是
OSError
的某个子类,如下文 OS exceptions 中所描述的。 具体的子类取决于最终的errno
值。 此行为仅在直接或通过别名来构造OSError
时发生,并且在子类化时不会被继承。errno
来自于 C 变量
errno
的数字错误码。winerror
在 Windows 下,此参数将给出原生的 Windows 错误码。 而
errno
属性将是该原生错误码在 POSIX 平台下的近似转换形式。在 Windows 下,如果 winerror 构造器参数是一个整数,则
errno
属性会根据 Windows 错误码来确定,而 errno 参数会被忽略。 在其他平台上,winerror 参数会被忽略,并且winerror
属性将不存在。strerror
操作系统所提供的相应错误信息。 它在 POSIX 平台中由 C 函数
perror()
来格式化,在 Windows 中则是由FormatMessage()
。filename
filename2
对于与文件系统路径有关 (例如
open()
或os.unlink()
) 的异常,filename
是传给函数的文件名。 对于涉及两个文件系统路径的函数 (例如os.rename()
),filename2
将是传给函数的第二个文件名。
在 3.3 版更改: EnvironmentError
, IOError
, WindowsError
, socket.error
, select.error
与 mmap.error
已被合并到 OSError
,构造器可能返回其中一个子类。
在 3.4 版更改: filename
属性现在是传给函数的原始文件名,而不是基于 filesystem encoding and error handler 进行编码或解码之后的名称。 此外,还添加了 filename2 构造器参数和属性。
- exception
OverflowError
当算术运算的结果大到无法表示时将被引发。 这对整数来说不可能发生(宁可引发 MemoryError
也不会放弃尝试)。 但是出于历史原因,有时也会在整数超出要求范围的情况下引发 OverflowError。 因为在 C 中缺少对浮点异常处理的标准化,大多数浮点运算都不会做检查。
- exception
RecursionError
此异常派生自 RuntimeError
。 它会在解释器检测发现超过最大递归深度 时被引发。
3.5 新版功能: 在此之前将只引发 RuntimeError
。
- exception
ReferenceError
此异常将在使用 weakref.proxy()
函数所创建的弱引用来访问该引用的某个已被作为垃圾回收的属性时被引发。
- exception
RuntimeError
当检测到一个不归属于任何其他类别的错误时将被引发。 关联的值是一个指明究竟发生了什么问题的字符串。
- exception
StopIteration
由内置函数 next()
和 iterator 的 __next__()
方法所引发,用来表示该迭代器不能产生下一项。
该异常对象只有一个属性 value
,它在构造该异常时作为参数给出,默认值为 None
。
当一个 generator 或 coroutine 函数返回时,将引发一个新的 StopIteration
实例,函数返回的值将被用作异常构造器的 value
形参。
如果某个生成器代码直接或间接地引发了 StopIteration
,它会被转换为 RuntimeError
(并将 StopIteration
保留为导致新异常的原因)。
在 3.3 版更改: 添加了 value
属性及其被生成器函数用作返回值的功能。
在 3.5 版更改: 引入了通过 from __future__ import generator_stop
来实现 RuntimeError 转换,参见 PEP 479。
在 3.7 版更改: 默认对所有代码启用 PEP 479: 在生成器中引发的 StopIteration
错误将被转换为 RuntimeError
。
- exception
StopAsyncIteration
必须由一个 asynchronous iterator 对象的 __anext__()
方法来引发以停止迭代操作。
3.5 新版功能.
exception
SyntaxError
(message, details)当解析器遇到语法错误时引发。 这可以发生在
import
语句,对内置函数compile()
,exec()
或eval()
的调用,或是读取原始脚本或标准输入(也包括交互模式)的时候。异常实例的
str()
只返回错误消息。 错误详情为一个元组,其成员也可在单独的属性中分别获取。filename
发生语法错误所在文件的名称。
lineno
发生错误所在文件中的行号。 行号索引从 1 开始:文件中首行的
lineno
为 1。offset
发生错误所在文件中的列号。 列号索引从 1 开始:行中首个字符的
offset
为 1。text
错误所涉及的源代码文本。
end_lineno
发生的错误在文件中的末尾行号。 这个索引是从 1 开始的:文件中首行的
lineno
为 1。end_offset
发生的错误在文件中的末尾列号。 这个索引是从 1 开始:行中首个字符的
offset
为 1。
对于 f-字符串字段中的错误,消息会带有 “f-string: “ 前缀并且其位置是基于替换表达式构建的文本中的位置。 例如,编译 f’Bad {a b} field’ 将产生这样的 args 属性: (‘f-string: …’, (‘’, 1, 2, ‘(a b)n’, 1, 5))。
在 3.10 版更改: 增加了 end_lineno
和 end_offset
属性。
- exception
IndentationError
与不正确的缩进相关的语法错误的基类。 这是 SyntaxError
的一个子类。
- exception
TabError
当缩进包含对制表符和空格符不一致的使用时将被引发。 这是 IndentationError
的一个子类。
- exception
SystemError
当解释器发现内部错误,但情况看起来尚未严重到要放弃所有希望时将被引发。 关联的值是一个指明发生了什么问题的字符串(表示为低层级的符号)。
你应当将此问题报告给你所用 Python 解释器的作者或维护人员。 请确认报告 Python 解释器的版本号 (sys.version
; 它也会在交互式 Python 会话开始时被打印出来),具体的错误消息(异常所关联的值)以及可能触发该错误的程序源码。
- exception
SystemExit
此异常由 sys.exit()
函数引发。 它继承自 BaseException
而不是 Exception
以确保不会被处理 Exception
的代码意外捕获。 这允许此异常正确地向上传播并导致解释器退出。 如果它未被处理,则 Python 解释器就将退出;不会打印任何栈回溯信息。 构造器接受的可选参数与传递给 sys.exit()
的相同。 如果该值为一个整数,则它指明系统退出状态码(会传递给 C 的 exit()
函数);如果该值为 None
,则退出状态码为零;如果该值为其他类型(例如字符串),则会打印对象的值并将退出状态码设为一。
对 sys.exit()
的调用会被转换为一个异常以便能执行清理处理程序 (try
语句的 finally
子句),并且使得调试器可以执行一段脚本而不必冒失去控制的风险。 如果绝对确实地需要立即退出(例如在调用 os.fork()
之后的子进程中)则可使用 os._exit()
.
code
传给构造器的退出状态码或错误信息(默认为 None
。)
- exception
TypeError
当一个操作或函数被应用于类型不适当的对象时将被引发。 关联的值是一个字符串,给出有关类型不匹配的详情。
此异常可以由用户代码引发,以表明尝试对某个对象进行的操作不受支持也不应当受支持。 如果某个对象应当支持给定的操作但尚未提供相应的实现,所要引发的适当异常应为 NotImplementedError
。
传入参数的类型错误 (例如在要求 int
时却传入了 list
) 应当导致 TypeError
,但传入参数的值错误 (例如传入要求范围之外的数值) 则应当导致 ValueError
。
- exception
UnboundLocalError
当在函数或方法中对某个局部变量进行引用,但该变量并未绑定任何值时将被引发。 此异常是 NameError
的一个子类。
exception
UnicodeError
当发生与 Unicode 相关的编码或解码错误时将被引发。 此异常是
ValueError
的一个子类。UnicodeError
具有一些描述编码或解码错误的属性。 例如err.object[err.start:err.end]
会给出导致编解码器失败的特定无效输入。encoding
引发错误的编码名称。
reason
描述特定编解码器错误的字符串。
object
编解码器试图要编码或解码的对象。
start
object
中无效数据的开始位置索引。end
object
中无效数据的末尾位置索引(不含)。
exception
UnicodeEncodeError
当在编码过程中发生与 Unicode 相关的错误时将被引发。 此异常是 UnicodeError
的一个子类。
- exception
UnicodeDecodeError
当在解码过程中发生与 Unicode 相关的错误时将被引发。 此异常是 UnicodeError
的一个子类。
- exception
UnicodeTranslateError
在转写过程中发生与 Unicode 相关的错误时将被引发。 此异常是 UnicodeError
的一个子类。
- exception
ValueError
当操作或函数接收到具有正确类型但值不适合的参数,并且情况不能用更精确的异常例如 IndexError
来描述时将被引发。
- exception
ZeroDivisionError
当除法或取余运算的第二个参数为零时将被引发。 关联的值是一个字符串,指明操作数和运算的类型。
下列异常被保留以与之前的版本相兼容;从 Python 3.3 开始,它们都是 OSError
的别名。
exception
EnvironmentError
exception
IOError
exception
WindowsError
限在 Windows 中可用。
OS 异常
下列异常均为 OSError
的子类,它们将根据系统错误代码被引发。
- exception
BlockingIOError
当一个操作会被某个设置为非阻塞操作的对象(例如套接字)所阻塞时将被引发。 对应于 errno
EAGAIN
, EALREADY
, EWOULDBLOCK
和 EINPROGRESS
。
除了 OSError
已有的属性,BlockingIOError
还有一个额外属性:
characters_written
一个整数,表示在被阻塞前已写入到流的字符数。 当使用来自
io
模块的带缓冲 I/O 类时此属性可用。exception
ChildProcessError
当一个子进程上的操作失败时将被引发。 对应于 errno
ECHILD
。
- exception
ConnectionError
与连接相关问题的基类。
其子类有 BrokenPipeError
, ConnectionAbortedError
, ConnectionRefusedError
和 ConnectionResetError
。
- exception
BrokenPipeError
ConnectionError
的子类,当试图写入另一端已被关闭的管道,或是试图写入已关闭写入的套接字时将被引发。 对应于 errno
EPIPE
和 ESHUTDOWN
。
- exception
ConnectionAbortedError
ConnectionError
的子类,当连接尝试被对端中止时将被引发。 对应于 errno
ECONNABORTED
。
- exception
ConnectionRefusedError
ConnectionError
的子类,当连接尝试被对端拒绝时将被引发。 对应于 errno
ECONNREFUSED
。
- exception
ConnectionResetError
ConnectionError
的子类,当连接被对端重置时将被引发。 对应于 errno
ECONNRESET
。
- exception
FileExistsError
当试图创建一个已存在的文件或目录时将被引发。 对应于 errno
EEXIST
。
- exception
FileNotFoundError
当所请求的文件或目录不存在时将被引发。 对应于 errno
ENOENT
。
- exception
InterruptedError
当系统调用被输入信号中断时将被引发。 对应于 errno
EINTR
。
在 3.5 版更改: 当系统调用被某个信号中断时,Python 现在会重试系统调用,除非该信号的处理程序引发了其它异常 (原理参见 PEP 475) 而不是引发 InterruptedError
。
- exception
IsADirectoryError
当请求对一个目录执行文件操作 (例如 os.remove()
) 将被引发。 对应于 errno
EISDIR
。
- exception
NotADirectoryError
当在非目录上请求目录操作 (例如 os.listdir()
) 时被引发。 在大多数 POSIX 平台上,它还可能在某个操作尝试以目录方式打开或遍历非目录时被引发。 对应于 errno
ENOTDIR
。
- exception
PermissionError
当在没有足够操作权限的情况下试图执行某个操作时将被引发 —— 例如缺少文件系统权限。 对应于 errno
EACCES
和 EPERM
。
- exception
ProcessLookupError
当给定的进程不存在时将被引发。 对应于 errno
ESRCH
。
- exception
TimeoutError
当一个系统函数发生系统级超时的情况下将被引发。 对应于 errno
ETIMEDOUT
。
3.3 新版功能: 添加了以上所有 OSError
的子类。
参见
PEP 3151 - 重写 OS 和 IO 异常的层次结构
警告
下列异常被用作警告类别
- exception
Warning
警告类别的基类。
- exception
UserWarning
用户代码所产生警告的基类。
- exception
DeprecationWarning
如果所发出的警告是针对其他 Python 开发者的,则以此作为与已弃用特性相关警告的基类。
会被默认警告过滤器忽略,在 __main__
模块中的情况除外 (PEP 565)。 启用 Python 开发模式 时会显示此警告。
The deprecation policy is described in PEP 387.
- exception
PendingDeprecationWarning
对于已过时并预计在未来弃用,但目前尚未弃用的特性相关警告的基类。
这个类很少被使用,因为针对未来可能的弃用发出警告的做法并不常见,而针对当前已有的弃用则推荐使用 DeprecationWarning
。
会被默认警告过滤器忽略。 启用 Python 开发模式 时会显示此警告。
The deprecation policy is described in PEP 387.
- exception
SyntaxWarning
与模糊的语法相关的警告的基类。
- exception
RuntimeWarning
与模糊的运行时行为相关的警告的基类。
- exception
FutureWarning
如果所发出的警告是针对以 Python 所编写应用的最终用户的,则以此作为与已弃用特性相关警告的基类。
- exception
ImportWarning
与在模块导入中可能的错误相关的警告的基类。
会被默认警告过滤器忽略。 启用 Python 开发模式 时会显示此警告。
- exception
UnicodeWarning
与 Unicode 相关的警告的基类。
- exception
EncodingWarning
与编码格式相关的警告的基类。
3.10 新版功能.
- exception
BytesWarning
与 bytes
和 bytearray
相关的警告的基类。
- exception
ResourceWarning
资源使用相关警告的基类。
会被默认警告过滤器忽略。 启用 Python 开发模式 时会显示此警告。
3.2 新版功能.
异常层次结构
内置异常的类层级结构如下:
BaseException
+-- SystemExit
+-- KeyboardInterrupt
+-- GeneratorExit
+-- Exception
+-- StopIteration
+-- StopAsyncIteration
+-- ArithmeticError
| +-- FloatingPointError
| +-- OverflowError
| +-- ZeroDivisionError
+-- AssertionError
+-- AttributeError
+-- BufferError
+-- EOFError
+-- ImportError
| +-- ModuleNotFoundError
+-- LookupError
| +-- IndexError
| +-- KeyError
+-- MemoryError
+-- NameError
| +-- UnboundLocalError
+-- OSError
| +-- BlockingIOError
| +-- ChildProcessError
| +-- ConnectionError
| | +-- BrokenPipeError
| | +-- ConnectionAbortedError
| | +-- ConnectionRefusedError
| | +-- ConnectionResetError
| +-- FileExistsError
| +-- FileNotFoundError
| +-- InterruptedError
| +-- IsADirectoryError
| +-- NotADirectoryError
| +-- PermissionError
| +-- ProcessLookupError
| +-- TimeoutError
+-- ReferenceError
+-- RuntimeError
| +-- NotImplementedError
| +-- RecursionError
+-- SyntaxError
| +-- IndentationError
| +-- TabError
+-- SystemError
+-- TypeError
+-- ValueError
| +-- UnicodeError
| +-- UnicodeDecodeError
| +-- UnicodeEncodeError
| +-- UnicodeTranslateError
+-- Warning
+-- DeprecationWarning
+-- PendingDeprecationWarning
+-- RuntimeWarning
+-- SyntaxWarning
+-- UserWarning
+-- FutureWarning
+-- ImportWarning
+-- UnicodeWarning
+-- BytesWarning
+-- EncodingWarning
+-- ResourceWarning
文本处理服务
在 二进制数据服务 之下描述的 codecs
模块也与文本处理高度相关。
string
—- 常见的字符串操作- 字符串常量
- 自定义字符串格式化
- 格式字符串语法
- 格式规格迷你语言
- 格式示例
- 模板字符串
- 辅助函数
re
—- 正则表达式操作- 正则表达式语法
- 模块内容
- 正则表达式对象 (正则对象)
- 匹配对象
- 正则表达式例子
- 检查对子
- 模拟 scanf()
- search() vs. match()
- 制作一个电话本
- 文字整理
- 查找所有副词
- 查找所有的副词及其位置
- 原始字符串标记
- 写一个词法分析器
difflib
—- 计算差异的辅助工具- SequenceMatcher 对象
- SequenceMatcher 的示例
- Differ 对象
- Differ 示例
- difflib 的命令行接口
textwrap
—- 文本自动换行与填充unicodedata
—- Unicode 数据库stringprep
—- 因特网字符串预备readline
—- GNU readline 接口- 初始化文件
- 行缓冲区
- 历史文件
- 历史列表
- 启动钩子
- Completion
- 示例
rlcompleter
—- GNU readline 的补全函数- Completer 对象
string
—- 常见的字符串操作
源代码: Lib/string.py
字符串常量
此模块中定义的常量为:
string.ascii_letters
下文所述 ascii_lowercase
和 ascii_uppercase
常量的拼连。 该值不依赖于语言区域。
string.ascii_lowercase
小写字母 'abcdefghijklmnopqrstuvwxyz'
。 该值不依赖于语言区域,不会发生改变。
string.ascii_uppercase
大写字母 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
。 该值不依赖于语言区域,不会发生改变。
string.digits
字符串 '0123456789'
。
string.hexdigits
字符串 '0123456789abcdefABCDEF'
。
string.octdigits
字符串 '01234567'
。
string.punctuation
由在 C
区域设置中被视为标点符号的 ASCII 字符所组成的字符串: !"#$%&'()*+,-./:;<=>?@[\]^_
{|}~`.
string.printable
由被视为可打印符号的 ASCII 字符组成的字符串。 这是 digits
, ascii_letters
, punctuation
和 whitespace
的总和。
string.whitespace
由被视为空白符号的 ASCII 字符组成的字符串。 其中包括空格、制表、换行、回车、进纸和纵向制表符。
自定义字符串格式化
内置的字符串类提供了通过使用 PEP 3101 所描述的 format()
方法进行复杂变量替换和值格式化的能力。 string
模块中的 Formatter
类允许你使用与内置 format()
方法相同的实现来创建并定制你自己的字符串格式化行为。
class string.Formatter
Formatter
类包含下列公有方法:
format
(format_string, /, \args, *kwargs)首要的 API 方法。 它接受一个格式字符串和任意一组位置和关键字参数。 它只是一个调用
vformat()
的包装器。在 3.7 版更改: 格式字符串参数现在是 仅限位置参数。
vformat
(format_string, args, kwargs)此函数执行实际的格式化操作。 它被公开为一个单独的函数,用于需要传入一个预定义字母作为参数,而不是使用
*args
和**kwargs
语法将字典解包为多个单独参数并重打包的情况。vformat()
完成将格式字符串分解为字符数据和替换字段的工作。 它会调用下文所述的几种不同方法。
此外,Formatter
还定义了一些旨在被子类替换的方法:
parse
(format_string)循环遍历 format_string 并返回一个由可迭代对象组成的元组 (literal_text, field_name, format_spec, conversion)。 它会被
vformat()
用来将字符串分解为文本字面值或替换字段。元组中的值在概念上表示一段字面文本加上一个替换字段。 如果没有字面文本(如果连续出现两个替换字段就会发生这种情况),则 literal_text 将是一个长度为零的字符串。 如果没有替换字段,则 field_name, format_spec 和 conversion 的值将为
None
。get_field
(field_name, args, kwargs)给定 field_name 作为
parse()
(见上文) 的返回值,将其转换为要格式化的对象。 返回一个元组 (obj, used_key)。 默认版本接受在 PEP 3101 所定义形式的字符串,例如 “0[name]“ 或 “label.title”。 args 和 kwargs 与传给vformat()
的一样。 返回值 used_key 与get_value()
的 key 形参具有相同的含义。get_value
(key, args, kwargs)提取给定的字段值。 key 参数将为整数或字符串。 如果是整数,它表示 args 中位置参数的索引;如果是字符串,它表示 kwargs 中的关键字参数名。
args 形参会被设为
vformat()
的位置参数列表,而 kwargs 形参会被设为由关键字参数组成的字典。对于复合字段名称,仅会为字段名称的第一个组件调用这些函数;后续组件会通过普通属性和索引操作来进行处理。
因此举例来说,字段表达式 ‘0.name’ 将导致调用
get_value()
时附带 key 参数值 0。 在get_value()
通过调用内置的getattr()
函数返回后将会查找name
属性。如果索引或关键字引用了一个不存在的项,则将引发
IndexError
或KeyError
。check_unused_args
(used_args, args, kwargs)在必要时实现对未使用参数进行检测。 此函数的参数是是格式字符串中实际引用的所有参数键的集合(整数表示位置参数,字符串表示名称参数),以及被传给 vformat 的 args 和 kwargs 的引用。 未使用参数的集合可以根据这些形参计算出来。 如果检测失败则
check_unused_args()
应会引发一个异常。format_field
(value, format_spec)format_field()
会简单地调用内置全局函数format()
。 提供该方法是为了让子类能够重载它。convert_field
(value, conversion)使用给定的转换类型(来自
parse()
方法所返回的元组)来转换(由get_field()
所返回的)值。 默认版本支持 ‘s’ (str), ‘r’ (repr) 和 ‘a’ (ascii) 等转换类型。
格式字符串语法
str.format()
方法和 Formatter
类共享相同的格式字符串语法(虽然对于 Formatter
来说,其子类可以定义它们自己的格式字符串语法)。 具体语法与 格式化字符串字面值 相似,但较为简单一些,并且关键的一点是不支持任意表达式。
格式字符串包含有以花括号 {}
括起来的“替换字段”。 不在花括号之内的内容被视为字面文本,会不加修改地复制到输出中。 如果你需要在字面文本中包含花括号字符,可以通过重复来转义: {{` and `}}
。
替换字段的语法如下:
replacement_field ::= "{" [field_name] ["!" conversion] [":" format_spec] "}" field_name ::= arg_name ("." attribute_name | "[" element_index "]")* arg_name ::= [identifier | digit+] attribute_name ::= identifier element_index ::= digit+ | index_string index_string ::= <any source character except "]"> + conversion ::= "r" | "s" | "a" format_spec ::= <described in the next section>
用不太正式的术语来描述,替换字段开头可以用一个 field_name 指定要对值进行格式化并取代替换字符被插入到输出结果的对象。 field_name 之后有可选的 conversion 字段,它是一个感叹号 '!'
加一个 format_spec,并以一个冒号 ':'
打头。 这些指明了替换值的非默认格式。
field_name 本身以一个数字或关键字 arg_name 打头。 如果为数字,则它指向一个位置参数,而如果为关键字,则它指向一个命名关键字参数。 如果格式字符串中的数字 arg_names 为 0, 1, 2, … 的序列,它们可以全部省略(而非部分省略),数字 0, 1, 2, … 将会按顺序自动插入。 由于 arg_name 不使用引号分隔,因此无法在格式字符串中指定任意的字典键 (例如字符串 '10'
或 ':-]'
)。 arg_name 之后可以带上任意数量的索引或属性表达式。 '.name'
形式的表达式会使用 getattr()
选择命名属性,而 '[index]'
形式的表达式会使用 __getitem__()
执行索引查找。
在 3.1 版更改: 位置参数说明符对于 str.format()
可以省略,因此 '{} {}'.format(a, b)
等价于 '{0} {1}'.format(a, b)
。
在 3.4 版更改: 位置参数说明符对于 Formatter
可以省略。
一些简单的格式字符串示例
"First, thou shalt count to {0}" # References first positional argument
"Bring me a {}" # Implicitly references the first positional argument
"From {} to {}" # Same as "From {0} to {1}"
"My quest is {name}" # References keyword argument 'name'
"Weight in tons {0.weight}" # 'weight' attribute of first positional arg
"Units destroyed: {players[0]}" # First element of keyword argument 'players'.
使用 conversion 字段在格式化之前进行类型强制转换。 通常,格式化值的工作由值本身的 __format__()
方法来完成。 但是,在某些情况下最好强制将类型格式化为一个字符串,覆盖其本身的格式化定义。 通过在调用 __format__()
之前将值转换为字符串,可以绕过正常的格式化逻辑。
目前支持的转换旗标有三种: '!s'
会对值调用 str()
,'!r'
调用 repr()
而 '!a'
则调用 ascii()
。
示例如下:
"Harold's a clever {0!s}" # Calls str() on the argument first
"Bring out the holy {name!r}" # Calls repr() on the argument first
"More {!a}" # Calls ascii() on the argument first
format_spec 字段包含值应如何呈现的规格描述,例如字段宽度、对齐、填充、小数精度等细节信息。 每种值类型可以定义自己的“格式化迷你语言”或对 format_spec 的解读方式。
大多数内置类型都支持同样的格式化迷你语言,具体描述见下一节。
format_spec 字段还可以在其内部包含嵌套的替换字段。 这些嵌套的替换字段可能包括字段名称、转换旗标和格式规格描述,但是不再允许更深层的嵌套。 format_spec 内部的替换字段会在解读 format_spec 字符串之前先被解读。 这将允许动态地指定特定值的格式。
格式规格迷你语言
“格式规格”在格式字符串所包含的替换字段内部使用,用于定义单个值应如何呈现 。 它们也可以被直接传给内置的 format()
函数。 每种可格式化的类型都可以自行定义如何对格式规格进行解读。
大多数内置类型都为格式规格实现了下列选项,不过某些格式化选项只被数值类型所支持。
一般约定空的格式描述将产生与在值上调用 str()
相同的结果。 非空格式描述通常会修改此结果。
标准格式说明符 的一般形式如下:
format_spec ::= [[fill]align][sign][#][0][width][grouping_option][.precision][type]
fill ::= <any character>
align ::= "<" | ">" | "=" | "^"
sign ::= "+" | "-" | " "
width ::= digit+
grouping_option ::= "_" | ","
precision ::= digit+
type ::= "b" | "c" | "d" | "e" | "E" | "f" | "F" | "g" | "G" | "n" | "o" | "s" | "x" | "X" | "%"
如果指定了一个有效的 align 值,则可以在该值前面加一个 fill 字符,它可以为任意字符,如果省略则默认为空格符。 在 格式化字符串字面值 或在使用 str.format()
方法时是无法使用花括号字面值 (“{
“ or “}
“) 作为 fill 字符的。 但是,通过嵌套替换字段插入花括号则是可以的。 这个限制不会影响 format()
函数。
各种对齐选项的含义如下:
选项 含意 ‘<’
强制字段在可用空间内左对齐(这是大多数对象的默认值)。 ‘>’
强制字段在可用空间内右对齐(这是数字的默认值)。 ‘=’
强制在符号(如果有)之后数码之前放置填充。 这被用于以 ‘+000000120’ 形式打印字段。 这个对齐选项仅对数字类型有效。 这是当 ‘0’ 紧接在字段宽度之前时的默认选项。 ‘^’
强制字段在可用空间内居中。
请注意,除非定义了最小字段宽度,否则字段宽度将始终与填充它的数据大小相同,因此在这种情况下,对齐选项没有意义。
sign 选项仅对数字类型有效,可以是以下之一:
选项 含意 ‘+’
表示标志应该用于正数和负数。 ‘-‘
表示标志应仅用于负数(这是默认行为)。 space 表示应在正数上使用前导空格,在负数上使用减号。
'#'
选项可让“替代形式”被用于执行转换。 替代形式会针对不同的类型分别定义。 此选项仅适用于整数、浮点数和复数类型。 对于整数类型,当使用二进制、八进制或十六进制输出时,此选项会为输出值分别添加相应的 '0b'
, '0o'
, '0x'
或 '0X'
前缀。 对于浮点数和复数类型,替代形式会使得转换结果总是包含小数点符号,即使其不带小数部分。 通常只有在带有小数部分的情况下,此类转换的结果中才会出现小数点符号。 此外,对于 'g'
和 'G'
转换,末尾的零不会从结果中被移除。
','
选项表示使用逗号作为千位分隔符。 对于感应区域设置的分隔符,请改用 'n'
整数表示类型。
在 3.1 版更改: 添加了 ','
选项 (另请参阅 PEP 378)。
'_'
选项表示对浮点表示类型和整数表示类型 'd'
使用下划线作为千位分隔符。 对于整数表示类型 'b'
, 'o'
, 'x'
和 'X'
,将为每 4 个数位插入一个下划线。 对于其他表示类型指定此选项则将导致错误。
在 3.6 版更改: 添加了 '_'
选项 (另请参阅 PEP 515)。
width 是一个定义最小总字段宽度的十进制整数,包括任何前缀、分隔符和其他格式化字符。 如果未指定,则字段宽度将由内容确定。
当未显式给出对齐方式时,在 width 字段前加一个零 ('0'
) 字段将为数字类型启用感知正负号的零填充。 这相当于设置 fill 字符为 '0'
且 alignment 类型为 '='
。
在 3.10 版更改: 在 width 字段之前添加 '0'
不会再影响字符串的默认对齐。
precision 是一个十进制数字,表示对于以 'f'
and 'F'
格式化的浮点数值要在小数点后显示多少个数位,或者对于以 'g'
或 'G'
格式化的浮点数值要在小数点前后共显示多少个数位。 对于非数字类型,该字段表示最大字段大小 —— 换句话说就是要使用多少个来自字段内容的字符。 对于整数值则不允许使用 precision。
最后,type 确定了数据应如何呈现。
可用的字符串表示类型是:
类型 含意 ‘s’
字符串格式。这是字符串的默认类型,可以省略。 None 和 ‘s’
一样。
可用的整数表示类型是:
类型 含意 ‘b’
二进制格式。 输出以 2 为基数的数字。 ‘c’
字符。在打印之前将整数转换为相应的unicode字符。 ‘d’
十进制整数。 输出以 10 为基数的数字。 ‘o’
八进制格式。 输出以 8 为基数的数字。 ‘x’
十六进制格式。 输出以 16 为基数的数字,使用小写字母表示 9 以上的数码。 ‘X’
十六进制格式。 输出以 16 为基数的数字,使用大写字母表示 9 以上的数码。 在指定 ‘#’
的情况下,前缀‘0x’
也将被转为大写形式‘0X’
。‘n’
数字。 这与 ‘d’
相似,不同之处在于它会使用当前区域设置来插入适当的数字分隔字符。None 和 ‘d’
相同。
在上述的表示类型之外,整数还可以通过下列的浮点表示类型来格式化 (除了 'n'
和 None
)。 当这样做时,会在格式化之前使用 float()
将整数转换为浮点数。
float
和 Decimal
值的可用表示类型有:
类型 含意 ‘e’
科学计数法。 对于一个给定的精度 p
,将数字格式化为以字母 ‘e’ 分隔系数和指数的科学计数法形式。 系数在小数点之前有一位,之后有p
位,总计p + 1
个有效数位。 如未指定精度,则会对float
采用小数点之后6
位精度,而对Decimal
则显示所有系数位。 如果小数点之后没有数位,则小数点也会被略去,除非使用了#
选项。‘E’
科学计数法。 与 ‘e’
相似,不同之处在于它使用大写字母 ‘E’ 作为分隔字符。‘f’
定点表示法。 对于一个给定的精度 p
,将数字格式化为在小数点之后恰好有p
位的小数形式。 如未指定精度,则会对float
采用小数点之后6
位精度,而对Decimal
则使用大到足够显示所有系数位的精度。 如果小数点之后没有数位,则小数点也会被略去,除非使用了#
选项。‘F’
定点表示。 与 ‘f’
相似,但会将nan
转为NAN
并将inf
转为INF
。‘g’
常规格式。 对于给定精度 p >= 1
,这会将数值舍入到p
个有效数位,再将结果以定点表示法或科学计数法进行格式化,具体取决于其值的大小。 精度0
会被视为等价于精度1
。准确的规则如下:假设使用表示类型‘e’
和精度p-1
进行格式化的结果具有指数值exp
。 那么如果m <= exp < p
,其中m
以 -4 表示浮点值而以 -6 表示Decimal
值,该数字将使用类型‘f’
和精度p-1-exp
进行格式化。 否则的话,该数字将使用表示类型‘e’
和精度p-1
进行格式化。 在两种情况下,都会从有效数字中移除无意义的末尾零,如果小数点之后没有余下数字则小数点也会被移除,除非使用了‘#’
选项。如未指定精度,会对float
采用6
个有效数位的精度。 对于Decimal
,结果的系数会沿用原值的系数数位;对于绝对值小于1e-6
的值以及最小有效数位的位值大于 1 的数值将会使用科学计数法,在其他情况下则会使用定点表示法。正负无穷,正负零和 nan 会分别被格式化为inf
,-inf
,0
,-0
和nan
,无论精度如何设定。‘G’
常规格式。 类似于 ‘g’
,不同之处在于当数值非常大时会切换为‘E’
。 无穷与 NaN 也会表示为大写形式。‘n’
数字。 这与 ‘g’
相似,不同之处在于它会使用当前区域设置来插入适当的数字分隔字符。‘%’
百分比。 将数字乘以 100 并显示为定点 ( ‘f’
) 格式,后面带一个百分号。None 对于 float
来说这类似于‘g’
,不同之处在于当使用定点表示法时,小数点之后将至少显示一位。 所用的精度会大到足以精确表示给定的值。对于Decimal
来说这相当于‘g’
或‘G’
,具体取决于当前 decimal 上下文的context.capitals
值。总体效果是将str()
的输出匹配为其他格式化因子所调整出的样子。
格式示例
本节包含 str.format()
语法的示例以及与旧式 %
格式化的比较。
该语法在大多数情况下与旧式的 %
格式化类似,只是增加了 {}
和 :
来取代 %
。 例如,,'%03.2f'
可以被改写为 '{:03.2f}'
。
新的格式语法还支持新增的不同选项,将在以下示例中说明。
按位置访问参数:
>>> '{0}, {1}, {2}'.format('a', 'b', 'c')
'a, b, c'
>>> '{}, {}, {}'.format('a', 'b', 'c') # 3.1+ only
'a, b, c'
>>> '{2}, {1}, {0}'.format('a', 'b', 'c')
'c, b, a'
>>> '{2}, {1}, {0}'.format(*'abc') # unpacking argument sequence
'c, b, a'
>>> '{0}{1}{0}'.format('abra', 'cad') # arguments' indices can be repeated
'abracadabra'
按名称访问参数:
>>> 'Coordinates: {latitude}, {longitude}'.format(latitude='37.24N', longitude='-115.81W')
'Coordinates: 37.24N, -115.81W'
>>> coord = {'latitude': '37.24N', 'longitude': '-115.81W'}
>>> 'Coordinates: {latitude}, {longitude}'.format(**coord)
'Coordinates: 37.24N, -115.81W'
访问参数的属性:
>>> c = 3-5j
>>> ('The complex number {0} is formed from the real part {0.real} '
... 'and the imaginary part {0.imag}.').format(c)
'The complex number (3-5j) is formed from the real part 3.0 and the imaginary part -5.0.'
>>> class Point:
... def __init__(self, x, y):
... self.x, self.y = x, y
... def __str__(self):
... return 'Point({self.x}, {self.y})'.format(self=self)
...
>>> str(Point(4, 2))
'Point(4, 2)'
访问参数的项:
>>> coord = (3, 5)
>>> 'X: {0[0]}; Y: {0[1]}'.format(coord)
'X: 3; Y: 5'
替代 %s
和 %r
:
>>> "repr() shows quotes: {!r}; str() doesn't: {!s}".format('test1', 'test2')
"repr() shows quotes: 'test1'; str() doesn't: test2"
对齐文本以及指定宽度:
>>> '{:<30}'.format('left aligned')
'left aligned '
>>> '{:>30}'.format('right aligned')
' right aligned'
>>> '{:^30}'.format('centered')
' centered '
>>> '{:*^30}'.format('centered') # use '*' as a fill char
'***********centered***********'
替代 %+f
, %-f
和 % f
以及指定正负号:
>>> '{:+f}; {:+f}'.format(3.14, -3.14) # show it always
'+3.140000; -3.140000'
>>> '{: f}; {: f}'.format(3.14, -3.14) # show a space for positive numbers
' 3.140000; -3.140000'
>>> '{:-f}; {:-f}'.format(3.14, -3.14) # show only the minus -- same as '{:f}; {:f}'
'3.140000; -3.140000'
替代 %x
和 %o
以及转换基于不同进位制的值:
>>> # format also supports binary numbers
>>> "int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}".format(42)
'int: 42; hex: 2a; oct: 52; bin: 101010'
>>> # with 0x, 0o, or 0b as prefix:
>>> "int: {0:d}; hex: {0:#x}; oct: {0:#o}; bin: {0:#b}".format(42)
'int: 42; hex: 0x2a; oct: 0o52; bin: 0b101010'
使用逗号作为千位分隔符:
>>> '{:,}'.format(1234567890)
'1,234,567,890'
表示为百分数:
>>> points = 19
>>> total = 22
>>> 'Correct answers: {:.2%}'.format(points/total)
'Correct answers: 86.36%'
使用特定类型的专属格式化:
>>> import datetime
>>> d = datetime.datetime(2010, 7, 4, 12, 15, 58)
>>> '{:%Y-%m-%d %H:%M:%S}'.format(d)
'2010-07-04 12:15:58'
嵌套参数以及更复杂的示例:
>>> for align, text in zip('<^>', ['left', 'center', 'right']):
... '{0:{fill}{align}16}'.format(text, fill=align, align=align)
...
'left<<<<<<<<<<<<'
'^^^^^center^^^^^'
'>>>>>>>>>>>right'
>>>
>>> octets = [192, 168, 0, 1]
>>> '{:02X}{:02X}{:02X}{:02X}'.format(*octets)
'C0A80001'
>>> int(_, 16)
3232235521
>>>
>>> width = 5
>>> for num in range(5,12):
... for base in 'dXob':
... print('{0:{width}{base}}'.format(num, base=base, width=width), end=' ')
... print()
...
5 5 5 101
6 6 6 110
7 7 7 111
8 8 10 1000
9 9 11 1001
10 A 12 1010
11 B 13 1011
模板字符串
模板字符串提供了由 PEP 292 所描述的更简便的字符串替换方式。 模板字符串的一个主要用例是文本国际化 (i18n),因为在此场景下,更简单的语法和功能使得文本翻译过程比使用 Python 的其他内置字符串格式化工具更为方便。 作为基于模板字符串构建以实现 i18n 的库的一个示例,请参看 flufl.i18n 包。
模板字符串支持基于 $
的替换,使用以下规则:
$$
为转义符号;它会被替换为单个的$
。$identifier
为替换占位符,它会匹配一个名为"identifier"
的映射键。 在默认情况下,"identifier"
限制为任意 ASCII 字母数字(包括下划线)组成的字符串,不区分大小写,以下划线或 ASCII 字母开头。 在$
字符之后的第一个非标识符字符将表明占位符的终结。${identifier}
等价于$identifier
。 当占位符之后紧跟着有效的但又不是占位符一部分的标识符字符时需要使用,例如"${noun}ification"
。
在字符串的其他位置出现 $
将导致引发 ValueError
。
string
模块提供了实现这些规则的 Template
类。 Template
有下列方法:
class string.Template
(template)
该构造器接受一个参数作为模板字符串。
substitute
(mapping={}, /, **kwds)执行模板替换,返回一个新字符串。 mapping 为任意字典类对象,其中的键将匹配模板中的占位符。 或者你也可以提供一组关键字参数,其中的关键字即对应占位符。 当同时给出 mapping 和 kwds 并且存在重复时,则以 kwds 中的占位符为优先。
safe_substitute
(mapping={}, /, **kwds)类似于
substitute()
,不同之处是如果有占位符未在 mapping 和 kwds 中找到,不是引发KeyError
异常,而是将原始占位符不加修改地显示在结果字符串中。 另一个与substitute()
的差异是任何在其他情况下出现的$
将简单地返回$
而不是引发ValueError
。此方法被认为“安全”,因为虽然仍有可能发生其他异常,但它总是尝试返回可用的字符串而不是引发一个异常。 从另一方面来说,
safe_substitute()
也可能根本算不上安全,因为它将静默地忽略错误格式的模板,例如包含多余的分隔符、不成对的花括号或不是合法 Python 标识符的占位符等等。
Template
的实例还提供一个公有数据属性:
template
这是作为构造器的 template 参数被传入的对象。 一般来说,你不应该修改它,但并不强制要求只读访问。
以下是一个如何使用模版的示例:
>>> from string import Template
>>> s = Template('$who likes $what')
>>> s.substitute(who='tim', what='kung pao')
'tim likes kung pao'
>>> d = dict(who='tim')
>>> Template('Give $who $100').substitute(d)
Traceback (most recent call last):
...
ValueError: Invalid placeholder in string: line 1, col 11
>>> Template('$who likes $what').substitute(d)
Traceback (most recent call last):
...
KeyError: 'what'
>>> Template('$who likes $what').safe_substitute(d)
'tim likes $what'
进阶用法:你可以派生 Template
的子类来自定义占位符语法、分隔符,或用于解析模板字符串的整个正则表达式。 为此目的,你可以重载这些类属性:
delimiter — 这是用来表示占位符的起始的分隔符的字符串字面值。 默认值为
$
。 请注意此参数 不能 为正则表达式,因为其实现将在必要时对此字符串调用re.escape()
。 还要注意你不能在创建类之后改变此分隔符(例如在子类的类命名空间中必须设置不同的分隔符)。idpattern — 这是用来描述不带花括号的占位符的模式的正则表达式。 默认值为正则表达式
(?a:[_a-z][_a-z0-9]*)
。 如果给出了此属性并且 braceidpattern 为None
则此模式也将作用于带花括号的占位符。注解
由于默认的 flags 为
re.IGNORECASE
,模式[a-z]
可以匹配某些非 ASCII 字符。 因此我们在这里使用了局部旗标a
。在 3.7 版更改: braceidpattern 可被用来定义对花括号内部和外部进行区分的模式。
braceidpattern — 此属性类似于 idpattern 但是用来描述带花括号的占位符的模式。 默认值
None
意味着回退到 idpattern (即在花括号内部和外部使用相同的模式)。 如果给出此属性,这将允许你为带花括号和不带花括号的占位符定义不同的模式。3.7 新版功能.
flags — 将在编译用于识别替换内容的正则表达式被应用的正则表达式旗标。 默认值为
re.IGNORECASE
。 请注意re.VERBOSE
总是会被加为旗标,因此自定义的 idpattern 必须遵循详细正则表达式的约定。3.2 新版功能.
作为另一种选项,你可以通过重载类属性 pattern 来提供整个正则表达式模式。 如果你这样做,该值必须为一个具有四个命名捕获组的正则表达式对象。 这些捕获组对应于上面已经给出的规则,以及无效占位符的规则:
- escaped — 这个组匹配转义序列,在默认模式中即
$$
。 - named — 这个组匹配不带花括号的占位符名称;它不应当包含捕获组中的分隔符。
- braced — 这个组匹配带有花括号的占位符名称;它不应当包含捕获组中的分隔符或者花括号。
- invalid — 这个组匹配任何其他分隔符模式(通常为单个分隔符),并且它应当出现在正则表达式的末尾。
辅助函数
string.capwords
(s, sep=None)
使用 str.split()
将参数拆分为单词,使用 str.capitalize()
将单词转为大写形式,使用 str.join()
将大写的单词进行拼接。 如果可选的第二个参数 sep 被省略或为 None
,则连续的空白字符会被替换为单个空格符并且开头和末尾的空白字符会被移除,否则 sep 会被用来拆分和拼接单词。
re
—- 正则表达式操作
源代码: Lib/re.py
本模块提供了与 Perl 语言类似的正则表达式匹配操作。
模式和被搜索的字符串既可以是 Unicode 字符串 (str
) ,也可以是8位字节串 (bytes
)。 但是,Unicode 字符串与 8 位字节串不能混用:也就是说,不能用字节串模式匹配 Unicode 字符串,反之亦然;同理,替换操作时,替换字符串的类型也必须与所用的模式和搜索字符串的类型一致。
正则表达式用反斜杠字符 ('\'
) 表示特殊形式,或是允许在使用特殊字符时,不引发它们的特殊含义。 这与 Python 的字符串字面值中对相同字符出于相同目的的用法产生冲突;例如,要匹配一个反斜杠字面值,用户可能必须写成 '\\\\'
来作为模式字符串,因为正则表达式必须为 \\
,而每个反斜杠在普通 Python 字符串字面值中又必须表示为 \\
。 而且还要注意,在 Python 的字符串字面值中使用的反斜杠如果有任何无效的转义序列,现在会触发 DeprecationWarning
,但以后会改为 SyntaxError
。 此行为即使对于正则表达式来说有效的转义字符同样会发生。
解决办法是对于正则表达式样式使用 Python 的原始字符串表示法;在带有 'r'
前缀的字符串字面值中,反斜杠不必做任何特殊处理。 因此 r"\n"
表示包含 '\'
和 'n'
两个字符的字符串,而 "\n"
则表示只包含一个换行符的字符串。 样式在 Python 代码中通常都使用原始字符串表示法。
绝大多数正则表达式操作都提供为模块函数和方法,在 编译正则表达式. 这些函数是一个捷径,不需要先编译正则对象,但是损失了一些优化参数。
参见
第三方模块 regex , 提供了与标准库 re
模块兼容的 API 接口,同时,还提供了更多功能和更全面的 Unicode 支持。
正则表达式语法
正则表达式(或 RE)指定了一组与之匹配的字符串;模块内的函数可以检查某个字符串是否与给定的正则表达式匹配(或者正则表达式是否匹配到字符串,这两种说法含义相同)。
正则表达式可以拼接;如果 A 和 B 都是正则表达式,则 AB 也是正则表达式。通常,如果字符串 p 匹配 A,并且另一个字符串 q 匹配 B,那么 pq 可以匹配 AB。除非 A 或者 B 包含低优先级操作,A 和 B 存在边界条件;或者命名组引用。所以,复杂表达式可以很容易的从这里描述的简单源语表达式构建。
正则表达式可以包含普通或者特殊字符。绝大部分普通字符,比如 'A'
, 'a'
, 或者 '0'
,都是最简单的正则表达式。它们就匹配自身。你可以拼接普通字符,所以 last
匹配字符串 'last'
. (在这一节的其他部分,我们将用 this special style
这种方式表示正则表达式,通常不带引号,要匹配的字符串用 'in single quotes'
,单引号形式。)
有些字符,比如 '|'
或者 '('
,属于特殊字符。 特殊字符既可以表示它的普通含义, 也可以影响它旁边的正则表达式的解释。
重复修饰符 (*
, +
, ?
, {m,n}
, 等) 不能直接嵌套。这样避免了非贪婪后缀 ?
修饰符,和其他实现中的修饰符产生的多义性。要应用一个内层重复嵌套,可以使用括号。 比如,表达式 (?:a{6})*
匹配6个 'a'
字符重复任意次数。
特殊字符有:
.
(点) 在默认模式,匹配除了换行的任意字符。如果指定了标签 DOTALL
,它将匹配包括换行符的任意字符。
^
(插入符号) 匹配字符串的开头, 并且在 MULTILINE
模式也匹配换行后的首个符号。
$
匹配字符串尾或者在字符串尾的换行符的前一个字符,在 MULTILINE
模式下也会匹配换行符之前的文本。 foo
匹配 ‘foo’ 和 ‘foobar’,但正则表达式 foo$
只匹配 ‘foo’。 更有趣的是,在 'foo1\nfoo2\n'
中搜索 foo.$
,通常匹配 ‘foo2’,但在 MULTILINE
模式下可以匹配到 ‘foo1’;在 'foo\n'
中搜索 $
会找到两个(空的)匹配:一个在换行符之前,一个在字符串的末尾。
*
对它前面的正则式匹配0到任意次重复, 尽量多的匹配字符串。 ab*
会匹配 'a'
,'ab'
,或者 'a'
后面跟随任意个 'b'
。
+
对它前面的正则式匹配1到任意次重复。 ab+
会匹配 'a'
后面跟随1个以上到任意个 'b'
,它不会匹配 'a'
。
?
对它前面的正则式匹配0到1次重复。 ab?
会匹配 'a'
或者 'ab'
。
*?, +?, ??
'*'
, '+'
,和 '?'
修饰符都是 贪婪的*;它们在字符串进行尽可能多的匹配。有时候并不需要这种行为。如果正则式 `<.>希望找到
‘ b ,它将会匹配整个字符串,而不仅是
‘。在修饰符之后添加
?将使样式以 *非贪婪
方式或者 :dfn:最小* 方式进行匹配; 尽量 *少* 的字符将会被匹配。 使用正则式
<.*?>将会仅仅匹配
‘‘`。
{m}
对其之前的正则式指定匹配 m 个重复;少于 m 的话就会导致匹配失败。比如, a{6}
将匹配6个 'a'
, 但是不能是5个。
{m,n}
对正则式进行 m 到 n 次匹配,在 m 和 n 之间取尽量多。 比如,a{3,5}
将匹配 3 到 5个 'a'
。忽略 m 意为指定下界为0,忽略 n 指定上界为无限次。 比如 a{4,}b
将匹配 'aaaab'
或者1000个 'a'
尾随一个 'b'
,但不能匹配 'aaab'
。逗号不能省略,否则无法辨别修饰符应该忽略哪个边界。
{m,n}?
前一个修饰符的非贪婪模式,只匹配尽量少的字符次数。比如,对于 'aaaaaa'
, a{3,5}
匹配 5个 'a'
,而 a{3,5}?
只匹配3个 'a'
。
\
转义特殊字符(允许你匹配 '*'
, '?'
, 或者此类其他),或者表示一个特殊序列;特殊序列之后进行讨论。
如果你没有使用原始字符串( r'raw'
)来表达样式,要牢记Python也使用反斜杠作为转义序列;如果转义序列不被Python的分析器识别,反斜杠和字符才能出现在字符串中。如果Python可以识别这个序列,那么反斜杠就应该重复两次。这将导致理解障碍,所以高度推荐,就算是最简单的表达式,也要使用原始字符串。
[]
用于表示一个字符集合。在一个集合中:
- 字符可以单独列出,比如
[amk]
匹配'a'
,'m'
, 或者'k'
。 - 可以表示字符范围,通过用
'-'
将两个字符连起来。比如[a-z]
将匹配任何小写ASCII字符,[0-5][0-9]
将匹配从00
到59
的两位数字,[0-9A-Fa-f]
将匹配任何十六进制数位。 如果-
进行了转义 (比如[a\-z]
)或者它的位置在首位或者末尾(如[-a]
或[a-]
),它就只表示普通字符'-'
。 - 特殊字符在集合中,失去它的特殊含义。比如
[(+*)]
只会匹配这几个文法字符'('
,'+'
,'*'
, or')'
。 - 字符类如
\w
或者\S
(如下定义) 在集合内可以接受,它们可以匹配的字符由ASCII
或者LOCALE
模式决定。 - 不在集合范围内的字符可以通过 取反 来进行匹配。如果集合首字符是
'^'
,所有 不 在集合内的字符将会被匹配,比如[^5]
将匹配所有字符,除了'5'
,[^^]
将匹配所有字符,除了'^'
.^
如果不在集合首位,就没有特殊含义。 - 在集合内要匹配一个字符
']'
,有两种方法,要么就在它之前加上反斜杠,要么就把它放到集合首位。比如,[()[\]{}]
和[]()[{}]
都可以匹配括号。 - Unicode Technical Standard #18 里的嵌套集合和集合操作支持可能在未来添加。这将会改变语法,所以为了帮助这个改变,一个
FutureWarning
将会在有多义的情况里被raise
,包含以下几种情况,集合由'['
开始,或者包含下列字符序列'--'
,'&&'
,'~~'
, 和'||'
。为了避免警告,需要将它们用反斜杠转义。
在 3.7 版更改: 如果一个字符串构建的语义在未来会改变的话,一个 FutureWarning
会 raise
。
|
A|B
, A 和 B 可以是任意正则表达式,创建一个正则表达式,匹配 A 或者 B. 任意个正则表达式可以用 '|'
连接。它也可以在组合(见下列)内使用。扫描目标字符串时, '|'
分隔开的正则样式从左到右进行匹配。当一个样式完全匹配时,这个分支就被接受。意思就是,一旦 A 匹配成功, B 就不再进行匹配,即便它能产生一个更好的匹配。或者说,'|'
操作符绝不贪婪。 如果要匹配 '|'
字符,使用 \|
, 或者把它包含在字符集里,比如 [|]
.
(...)
(组合),匹配括号内的任意正则表达式,并标识出组合的开始和结尾。匹配完成后,组合的内容可以被获取,并可以在之后用 \number
转义序列进行再次匹配,之后进行详细说明。要匹配字符 '('
或者 ')'
, 用 \(
或 \)
, 或者把它们包含在字符集合里: [(]
, [)]
.
(?…)
这是个扩展标记法 (一个 '?'
跟随 '('
并无含义)。 '?'
后面的第一个字符决定了这个构建采用什么样的语法。这种扩展通常并不创建新的组合; (?P<name>...)
是唯一的例外。 以下是目前支持的扩展。
(?aiLmsux)
( 'a'
, 'i'
, 'L'
, 'm'
, 's'
, 'u'
, 'x'
中的一个或多个) 这个组合匹配一个空字符串;这些字符对正则表达式设置以下标记 re.A
(只匹配ASCII字符), re.I
(忽略大小写), re.L
(语言依赖), re.M
(多行模式), re.S
(点dot匹配全部字符), re.U
(Unicode匹配), and re.X
(冗长模式)。 如果你想将这些标记包含在正则表达式中,这个方法就很有用,免去了在 re.compile()
中传递 flag 参数。标记应该在表达式字符串首位表示。
(?:…)
正则括号的非捕获版本。 匹配在括号内的任何正则表达式,但该分组所匹配的子字符串 不能 在执行匹配后被获取或是之后在模式中被引用。
(?aiLmsux-imsx:…)
('a'
, 'i'
, 'L'
, 'm'
, 's'
, 'u'
, 'x'
中的0或者多个, 之后可选跟随 '-'
在后面跟随 'i'
, 'm'
, 's'
, 'x'
中的一到多个 .) 这些字符为表达式的其中一部分 设置 或者 去除 相应标记 re.A
(只匹配ASCII), re.I
(忽略大小写), re.L
(语言依赖), re.M
(多行), re.S
(点匹配所有字符), re.U
(Unicode匹配), and re.X
(冗长模式)。
'a'
, 'L'
and 'u'
作为内联标记是相互排斥的, 所以它们不能结合在一起,或者跟随 '-'
。 当他们中的某个出现在内联组中,它就覆盖了括号组内的匹配模式。在Unicode样式中, (?a:...)
切换为 只匹配ASCII, (?u:...)
切换为Unicode匹配 (默认). 在byte样式中 (?L:...)
切换为语言依赖模式, (?a:...)
切换为 只匹配ASCII (默认)。这种方式只覆盖组合内匹配,括号外的匹配模式不受影响。
3.6 新版功能.
在 3.7 版更改: 符号 'a'
, 'L'
和 'u'
同样可以用在一个组合内。
(?P<name>…)
(命名组合)类似正则组合,但是匹配到的子串组在外部是通过定义的 name 来获取的。组合名必须是有效的Python标识符,并且每个组合名只能用一个正则表达式定义,只能定义一次。一个符号组合同样是一个数字组合,就像这个组合没有被命名一样。
命名组合可以在三种上下文中引用。如果样式是 (?P<quote>['"]).*?(?P=quote)
(也就是说,匹配单引号或者双引号括起来的字符串):
引用组合 “quote” 的上下文 | 引用方法 |
---|---|
在正则式自身内 | (?P=quote) (如示) \1 |
处理匹配对象 m | m.group(‘quote’) m.end(‘quote’) (等) |
传递到 re.sub() 里的 repl 参数中 |
\g<quote> \g<1> \1 |
(?P=name)
反向引用一个命名组合;它匹配前面那个叫 name 的命名组中匹配到的串同样的字串。
(?#…)
注释;里面的内容会被忽略。
(?=…)
匹配 …
的内容,但是并不消费样式的内容。这个叫做 lookahead assertion。比如, Isaac (?=Asimov)
匹配 'Isaac '
只有在后面是 'Asimov'
的时候。
(?!…)
匹配 …
不符合的情况。这个叫 negative lookahead assertion (前视取反)。比如说, Isaac (?!Asimov)
只有后面 不 是 'Asimov'
的时候才匹配 'Isaac '
。
(?<=…)
匹配字符串的当前位置,它的前面匹配 ...
的内容到当前位置。这叫 positive lookbehind assertion (正向后视断定)。 (?<=abc)def
会在 'abcdef'
中找到一个匹配,因为后视会往后看3个字符并检查是否包含匹配的样式。包含的匹配样式必须是定长的,意思就是 abc
或 a|b
是允许的,但是 a*
和 a{3,4}
不可以。注意以 positive lookbehind assertions 开始的样式,如 (?<=abc)def
,并不是从 a 开始搜索,而是从 d 往回看的。你可能更加愿意使用 search()
函数,而不是 match()
函数:
>>> import re
>>> m = re.search('(?<=abc)def', 'abcdef')
>>> m.group(0)
'def'
这个例子搜索一个跟随在连字符后的单词:
>>> m = re.search(r'(?<=-)\w+', 'spam-egg')
>>> m.group(0)
'egg'
在 3.5 版更改: 添加定长组合引用的支持。
(?<!…)
匹配当前位置之前不是 ...
的样式。这个叫 negative lookbehind assertion (后视断定取非)。类似正向后视断定,包含的样式匹配必须是定长的。由 negative lookbehind assertion 开始的样式可以从字符串搜索开始的位置进行匹配。
(?(id/name)yes-pattern|no-pattern)
如果给定的 id 或 name 存在,将会尝试匹配 yes-pattern
,否则就尝试匹配 no-pattern
,no-pattern
可选,也可以被忽略。比如, (<)?(\w+@\w+(?:\.\w+)+)(?(1)>|$)
是一个email样式匹配,将匹配 '<user@host.com>'
或 'user@host.com'
,但不会匹配 '<user@host.com'
,也不会匹配 'user@host.com>'
。
由 '\'
和一个字符组成的特殊序列在以下列出。 如果普通字符不是ASCII数位或者ASCII字母,那么正则样式将匹配第二个字符。比如,\$
匹配字符 '$'
.
\number
匹配数字代表的组合。每个括号是一个组合,组合从1开始编号。比如 (.+) \1
匹配 'the the'
或者 '55 55'
, 但不会匹配 'thethe'
(注意组合后面的空格)。这个特殊序列只能用于匹配前面99个组合。如果 number 的第一个数位是0, 或者 number 是三个八进制数,它将不会被看作是一个组合,而是八进制的数字值。在 '['
和 ']'
字符集合内,任何数字转义都被看作是字符。
\A
只匹配字符串开始。
\b
匹配空字符串,但只在单词开始或结尾的位置。一个单词被定义为一个单词字符的序列。注意,通常 \b
定义为 \w
和 \W
字符之间,或者 \w
和字符串开始/结尾的边界, 意思就是 r'\bfoo\b'
匹配 'foo'
, 'foo.'
, '(foo)'
, 'bar foo baz'
但不匹配 'foobar'
或者 'foo3'
。
默认情况下,Unicode字母和数字是在Unicode样式中使用的,但是可以用 ASCII
标记来更改。如果 LOCALE
标记被设置的话,词的边界是由当前语言区域设置决定的,\b
表示退格字符,以便与Python字符串文本兼容。
\B
匹配空字符串,但 不 能在词的开头或者结尾。意思就是 r'py\B'
匹配 'python'
, 'py3'
, 'py2'
, 但不匹配 'py'
, 'py.'
, 或者 'py!'
. \B
是 \b
的取非,所以Unicode样式的词语是由Unicode字母,数字或下划线构成的,虽然可以用 ASCII
标志来改变。如果使用了 LOCALE
标志,则词的边界由当前语言区域设置。
\d
对于 Unicode (str) 样式:
匹配任何Unicode十进制数(就是在Unicode字符目录[Nd]里的字符)。这包括了
[0-9]
,和很多其他的数字字符。如果设置了ASCII
标志,就只匹配[0-9]
。对于8位(bytes)样式:
匹配任何十进制数,就是
[0-9]
。
\D
匹配任何非十进制数字的字符。就是 \d
取非。 如果设置了 ASCII
标志,就相当于 [^0-9]
。
\s
对于 Unicode (str) 样式:
匹配任何Unicode空白字符(包括
[ \t\n\r\f\v]
,还有很多其他字符,比如不同语言排版规则约定的不换行空格)。如果ASCII
被设置,就只匹配[ \t\n\r\f\v]
。对于8位(bytes)样式:
匹配ASCII中的空白字符,就是
[ \t\n\r\f\v]
。
\S
匹配任何非空白字符。就是 \s
取非。如果设置了 ASCII
标志,就相当于 [^ \t\n\r\f\v]
。
\w
对于 Unicode (str) 样式:
匹配Unicode词语的字符,包含了可以构成词语的绝大部分字符,也包括数字和下划线。如果设置了
ASCII
标志,就只匹配[a-zA-Z0-9_]
。对于8位(bytes)样式:
匹配ASCII字符中的数字和字母和下划线,就是
[a-zA-Z0-9_]
。如果设置了LOCALE
标记,就匹配当前语言区域的数字和字母和下划线。
\W
匹配非单词字符的字符。这与 \w
正相反。如果使用了 ASCII
旗标,这就等价于 [^a-zA-Z0-9_]
。如果使用了 LOCALE
旗标,则会匹配当前区域中既非字母数字也非下划线的字符。
\Z
只匹配字符串尾。
绝大部分Python的标准转义字符也被正则表达式分析器支持。:
\a \b \f \n\N \r \t \u\U \v \x \\
(注意 \b
被用于表示词语的边界,它只在字符集合内表示退格,比如 [\b]
。)
'\u'
, '\U'
和 '\N'
转义序列只在 Unicode 模式中可被识别。 在 bytes 模式中它们会导致错误。 未知的 ASCII 字母转义序列保留在未来使用,会被当作错误来处理。
八进制转义包含为一个有限形式。如果首位数字是 0, 或者有三个八进制数位,那么就认为它是八进制转义。其他的情况,就看作是组引用。对于字符串文本,八进制转义最多有三个数位长。
在 3.3 版更改: 增加了 '\u'
和 '\U'
转义序列。
在 3.6 版更改: 由 '\'
和一个ASCII字符组成的未知转义会被看成错误。
在 3.8 版更改: 添加了 '\N{name}'
转义序列。 与在字符串字面值中一样,它扩展了命名 Unicode 字符 (例如 '\N{EM DASH}'
)。
模块内容
模块定义了几个函数、常量,和一个异常。有些函数是编译后的正则表达式方法的简化版本(少了一些特性)。重要的应用程序大多会在使用前先编译正则表达式。
在 3.6 版更改: 标志常量现在是 RegexFlag
类的实例,这个类是 enum.IntFlag
的子类。
re.compile
(pattern, flags=0)
将正则表达式的样式编译为一个 正则表达式对象 (正则对象),可以用于匹配,通过这个对象的方法 match()
, search()
以及其他如下描述。
这个表达式的行为可以通过指定 标记 的值来改变。值可以是以下任意变量,可以通过位的OR操作来结合( |
操作符)。
序列
prog = re.compile(pattern)
result = prog.match(string)
等价于
result = re.match(pattern, string)
如果需要多次使用这个正则表达式的话,使用 re.compile()
和保存这个正则对象以便复用,可以让程序更加高效。
注解
通过 re.compile()
编译后的样式,和模块级的函数会被缓存, 所以少数的正则表达式使用无需考虑编译的问题。
re.A
re.ASCII
让 \w
, \W
, \b
, \B
, \d
, \D
, \s
和 \S
只匹配ASCII,而不是Unicode。这只对Unicode样式有效,会被byte样式忽略。相当于前面语法中的内联标志 (?a)
。
注意,为了保持向后兼容, re.U
标记依然存在(还有他的同义 re.UNICODE
和嵌入形式 (?u)
) , 但是这些在 Python 3 是冗余的,因为默认字符串已经是Unicode了(并且Unicode匹配不允许byte出现)。
re.DEBUG
显示编译时的debug信息,没有内联标记。
re.I
re.IGNORECASE
进行忽略大小写匹配;表达式如 [A-Z]
也会匹配小写字符。Unicode匹配(比如 Ü
匹配 ü
)同样有用,除非设置了 re.ASCII
标记来禁用非ASCII匹配。当前语言区域不会改变这个标记,除非设置了 re.LOCALE
标记。这个相当于内联标记 (?i)
。
注意,当设置了 IGNORECASE
标记,搜索Unicode样式 [a-z]
或 [A-Z]
的结合时,它将会匹配52个ASCII字符和4个额外的非ASCII字符: ‘İ’ (U+0130, 拉丁大写的 I 带个点在上面), ‘ı’ (U+0131, 拉丁小写没有点的 I ), ‘ſ’ (U+017F, 拉丁小写长 s) and ‘K’ (U+212A, 开尔文符号).如果使用 ASCII
标记,就只匹配 ‘a’ 到 ‘z’ 和 ‘A’ 到 ‘Z’ 。
re.L
re.LOCALE
由当前语言区域决定 \w
, \W
, \b
, \B
和大小写敏感匹配。这个标记只能对byte样式有效。这个标记不推荐使用,因为语言区域机制很不可靠,它一次只能处理一个 “习惯”,而且只对8位字节有效。Unicode匹配在Python 3 里默认启用,并可以处理不同语言。 这个对应内联标记 (?L)
。
在 3.6 版更改: re.LOCALE
只能用于byte样式,而且不能和 re.ASCII
一起用。
在 3.7 版更改: 设置了 re.LOCALE
标记的编译正则对象不再在编译时依赖语言区域设置。语言区域设置只在匹配的时候影响其结果。
re.M
re.MULTILINE
设置以后,样式字符 '^'
匹配字符串的开始,和每一行的开始(换行符后面紧跟的符号);样式字符 '$'
匹配字符串尾,和每一行的结尾(换行符前面那个符号)。默认情况下,’^’
匹配字符串头,'$'
匹配字符串尾。对应内联标记 (?m)
。
re.S
re.DOTALL
让 '.'
特殊字符匹配任何字符,包括换行符;如果没有这个标记,'.'
就匹配 除了 换行符的其他任意字符。对应内联标记 (?s)
。
re.X
re.VERBOSE
这个标记允许你编写更具可读性更友好的正则表达式。通过分段和添加注释。空白符号会被忽略,除非在一个字符集合当中或者由反斜杠转义,或者在 *?
, (?:
or (?P<…>
分组之内。当一个行内有 #
不在字符集和转义序列,那么它之后的所有字符都是注释。
意思就是下面两个正则表达式等价地匹配一个十进制数字:
a = re.compile(r"""\d + # the integral part
\. # the decimal point
\d * # some fractional digits""", re.X)
b = re.compile(r"\d+\.\d*")
对应内联标记 (?x)
。
re.search
(pattern, string, flags=0)
扫描整个 字符串 找到匹配样式的第一个位置,并返回一个相应的 匹配对象。如果没有匹配,就返回一个 None
; 注意这和找到一个零长度匹配是不同的。
re.match
(pattern, string, flags=0)
如果 string 开始的0或者多个字符匹配到了正则表达式样式,就返回一个相应的 匹配对象 。 如果没有匹配,就返回 None
;注意它跟零长度匹配是不同的。
注意即便是 MULTILINE
多行模式, re.match()
也只匹配字符串的开始位置,而不匹配每行开始。
如果你想定位 string 的任何位置,使用 search()
来替代
re.fullmatch
(pattern, string, flags=0)
如果整个 string 匹配到正则表达式样式,就返回一个相应的 匹配对象 。 否则就返回一个 None
;注意这跟零长度匹配是不同的。
3.4 新版功能.
re.split
(pattern, string, maxsplit=0, flags=0)
用 pattern 分开 string 。 如果在 pattern 中捕获到括号,那么所有的组里的文字也会包含在列表里。如果 maxsplit 非零, 最多进行 maxsplit 次分隔, 剩下的字符全部返回到列表的最后一个元素。
>>> re.split(r'\W+', 'Words, words, words.')
['Words', 'words', 'words', '']
>>> re.split(r'(\W+)', 'Words, words, words.')
['Words', ', ', 'words', ', ', 'words', '.', '']
>>> re.split(r'\W+', 'Words, words, words.', 1)
['Words', 'words, words.']
>>> re.split('[a-f]+', '0a3B9', flags=re.IGNORECASE)
['0', '3', '9']
如果分隔符里有捕获组合,并且匹配到字符串的开始,那么结果将会以一个空字符串开始。对于结尾也是一样
>>> re.split(r'(\W+)', '...words, words...')
['', '...', 'words', ', ', 'words', '...', '']
这样的话,分隔组将会出现在结果列表中同样的位置。
样式的空匹配仅在与前一个空匹配不相邻时才会拆分字符串。
>>> re.split(r'\b', 'Words, words, words.')
['', 'Words', ', ', 'words', ', ', 'words', '.']
>>> re.split(r'\W*', '...words...')
['', '', 'w', 'o', 'r', 'd', 's', '', '']
>>> re.split(r'(\W*)', '...words...')
['', '...', '', '', 'w', '', 'o', '', 'r', '', 'd', '', 's', '...', '', '', '']
在 3.1 版更改: 增加了可选标记参数。
在 3.7 版更改: 增加了空字符串的样式分隔。
re.findall
(pattern, string, flags=0)
Return all non-overlapping matches of pattern in string, as a list of strings or tuples. The string is scanned left-to-right, and matches are returned in the order found. Empty matches are included in the result.
The result depends on the number of capturing groups in the pattern. If there are no groups, return a list of strings matching the whole pattern. If there is exactly one group, return a list of strings matching that group. If multiple groups are present, return a list of tuples of strings matching the groups. Non-capturing groups do not affect the form of the result.
>>> re.findall(r'\bf[a-z]*', 'which foot or hand fell fastest')
['foot', 'fell', 'fastest']
>>> re.findall(r'(\w+)=(\d+)', 'set width=20 and height=10')
[('width', '20'), ('height', '10')]
在 3.7 版更改: 非空匹配现在可以在前一个空匹配之后出现了。
re.finditer
(pattern, string, flags=0)
pattern 在 string 里所有的非重复匹配,返回为一个迭代器 iterator 保存了 匹配对象 。 string 从左到右扫描,匹配按顺序排列。空匹配也包含在结果里。
在 3.7 版更改: 非空匹配现在可以在前一个空匹配之后出现了。
re.sub
(pattern, repl, string, count=0, flags=0)
返回通过使用 repl 替换在 string 最左边非重叠出现的 pattern 而获得的字符串。 如果样式没有找到,则不加改变地返回 string*。 *repl 可以是字符串或函数;如为字符串,则其中任何反斜杠转义序列都会被处理。 也就是说,\n
会被转换为一个换行符,\r
会被转换为一个回车符,依此类推。 未知的 ASCII 字符转义序列保留在未来使用,会被当作错误来处理。 其他未知转义序列例如 \&
会保持原样。 向后引用像是 \6
会用样式中第 6 组所匹配到的子字符串来替换。 例如:
>>> re.sub(r'def\s+([a-zA-Z_][a-zA-Z_0-9]*)\s*\(\s*\):',
... r'static PyObject*\npy_\1(void)\n{',
... 'def myfunc():')
'static PyObject*\npy_myfunc(void)\n{'
如果 repl 是一个函数,那它会对每个非重复的 pattern 的情况调用。这个函数只能有一个 匹配对象 参数,并返回一个替换后的字符串。比如
>>> def dashrepl(matchobj):
... if matchobj.group(0) == '-': return ' '
... else: return '-'
>>> re.sub('-{1,2}', dashrepl, 'pro----gram-files')
'pro--gram files'
>>> re.sub(r'\sAND\s', ' & ', 'Baked Beans And Spam', flags=re.IGNORECASE)
'Baked Beans & Spam'
样式可以是一个字符串或者一个 样式对象 。
可选参数 count 是要替换的最大次数;count 必须是非负整数。如果省略这个参数或设为 0,所有的匹配都会被替换。 样式的空匹配仅在与前一个空匹配不相邻时才会被替换,所以 sub('x*', '-', 'abxd')
返回 '-a-b--d-'
。
在字符串类型的 repl 参数里,如上所述的转义和向后引用中,\g<name>
会使用命名组合 name
,(在 (?P<name>…)
语法中定义) \g<number>
会使用数字组;\g<2>
就是 \2
,但它避免了二义性,如 \g<2>0
。 \20
就会被解释为组20,而不是组2后面跟随一个字符 '0'
。向后引用 \g<0>
把 pattern 作为一整个组进行引用。
在 3.1 版更改: 增加了可选标记参数。
在 3.5 版更改: 不匹配的组合替换为空字符串。
在 3.6 版更改: pattern 中的未知转义(由 '\'
和一个 ASCII 字符组成)被视为错误。
在 3.7 版更改: repl 中的未知转义(由 '\'
和一个 ASCII 字符组成)被视为错误。
在 3.7 版更改: 样式中的空匹配相邻接时会被替换。
re.subn
(pattern, repl, string, count=0, flags=0)
行为与 sub()
相同,但是返回一个元组 (字符串, 替换次数)
.
在 3.1 版更改: 增加了可选标记参数。
在 3.5 版更改: 不匹配的组合替换为空字符串。
re.escape
(pattern)
转义 pattern 中的特殊字符。如果你想对任意可能包含正则表达式元字符的文本字符串进行匹配,它就是有用的。比如
>>> print(re.escape('https://www.python.org'))
https://www\.python\.org
>>> legal_chars = string.ascii_lowercase + string.digits + "!#$%&'*+-.^_`|~:"
>>> print('[%s]+' % re.escape(legal_chars))
[abcdefghijklmnopqrstuvwxyz0123456789!\#\$%\&'\*\+\-\.\^_`\|\~:]+
>>> operators = ['+', '-', '*', '/', '**']
>>> print('|'.join(map(re.escape, sorted(operators, reverse=True))))
/|\-|\+|\*\*|\*
这个函数不能被用于 sub()
和 subn()
的替换字符串,只有反斜杠应该被转义。 例如:
>>> digits_re = r'\d+'
>>> sample = '/usr/sbin/sendmail - 0 errors, 12 warnings'
>>> print(re.sub(digits_re, digits_re.replace('\\', r'\\'), sample))
/usr/sbin/sendmail - \d+ errors, \d+ warnings
在 3.3 版更改: '_'
不再被转义。
在 3.7 版更改: 只有在正则表达式中具有特殊含义的字符才会被转义。 因此, '!'
, '"'
, '%'
, "'"
, ','
, '/'
, ':'
, ';'
, '<'
, '='
, '>'
, '@'
和 "
“` 将不再会被转义。
re.purge
()
清除正则表达式的缓存。
exception re.error
(msg, pattern=None, pos=None)
当传递给函数的正则表达式不合法(比如括号不匹配),或者在编译或匹配过程中出现其他错误时,会引发异常。所给字符串不匹配所给模式不会引发异常。异常实例有以下附加属性:
msg
未格式化的错误消息。
pattern
正则表达式的模式串。
pos
编译失败的 pattern 的位置索引(可以是
None
)。lineno
对应 pos (可以是
None
) 的行号。colno
对应 pos (可以是
None
) 的列号。
在 3.5 版更改: 增加了额外的属性。
正则表达式对象 (正则对象)
编译后的正则表达式对象支持以下方法和属性:
Pattern.search
(string[, pos[, endpos]])
扫描整个 string 寻找第一个匹配的位置, 并返回一个相应的 匹配对象。如果没有匹配,就返回 None
;注意它和零长度匹配是不同的。
可选的第二个参数 pos 给出了字符串中开始搜索的位置索引;默认为 0
,它不完全等价于字符串切片; '^'
样式字符匹配字符串真正的开头,和换行符后面的第一个字符,但不会匹配索引规定开始的位置。
可选参数 endpos 限定了字符串搜索的结束;它假定字符串长度到 endpos , 所以只有从 pos
到 endpos - 1
的字符会被匹配。如果 endpos 小于 pos*,就不会有匹配产生;另外,如果 *rx 是一个编译后的正则对象, rx.search(string, 0, 50)
等价于 rx.search(string[:50], 0)
。
>>> pattern = re.compile("d")
>>> pattern.search("dog") # Match at index 0
<re.Match object; span=(0, 1), match='d'>
>>> pattern.search("dog", 1) # No match; search doesn't include the "d"
Pattern.match
(string[, pos[, endpos]])
如果 string 的 开始位置 能够找到这个正则样式的任意个匹配,就返回一个相应的 匹配对象。如果不匹配,就返回 None
;注意它与零长度匹配是不同的。
可选参数 pos 和 endpos 与 search()
含义相同。
>>> pattern = re.compile("o")
>>> pattern.match("dog") # No match as "o" is not at the start of "dog".
>>> pattern.match("dog", 1) # Match as "o" is the 2nd character of "dog".
<re.Match object; span=(1, 2), match='o'>
如果你想定位匹配在 string 中的位置,使用 search()
来替代。
Pattern.fullmatch
(string[, pos[, endpos]])
如果整个 string 匹配这个正则表达式,就返回一个相应的 匹配对象 。 否则就返回 None
; 注意跟零长度匹配是不同的。
可选参数 pos 和 endpos 与 search()
含义相同。
>>> pattern = re.compile("o[gh]")
>>> pattern.fullmatch("dog") # No match as "o" is not at the start of "dog".
>>> pattern.fullmatch("ogre") # No match as not the full string matches.
>>> pattern.fullmatch("doggie", 1, 3) # Matches within given limits.
<re.Match object; span=(1, 3), match='og'>
3.4 新版功能.
Pattern.split
(string, maxsplit=0)
等价于 split()
函数,使用了编译后的样式。
Pattern.findall
(string[, pos[, endpos]])
类似函数 findall()
, 使用了编译后样式,但也可以接收可选参数 pos 和 endpos ,限制搜索范围,就像 search()
。
Pattern.finditer
(string[, pos[, endpos]])
类似函数 finditer()
, 使用了编译后样式,但也可以接收可选参数 pos 和 endpos ,限制搜索范围,就像 search()
。
Pattern.sub
(repl, string, count=0)
等价于 sub()
函数,使用了编译后的样式。
Pattern.subn
(repl, string, count=0)
等价于 subn()
函数,使用了编译后的样式。
Pattern.flags
正则匹配标记。这是可以传递给 compile()
的参数,任何 (?…)
内联标记,隐性标记比如 UNICODE
的结合。
Pattern.groups
捕获到的模式串中组的数量。
Pattern.groupindex
映射由 (?P<id>)
定义的命名符号组合和数字组合的字典。如果没有符号组,那字典就是空的。
Pattern.pattern
编译对象的原始样式字符串。
在 3.7 版更改: 添加 copy.copy()
和 copy.deepcopy()
函数的支持。编译后的正则表达式对象被认为是原子性的。
匹配对象
匹配对象总是有一个布尔值 True
。如果没有匹配的话 match()
和 search()
返回 None
所以你可以简单的用 if
语句来判断是否匹配
match = re.search(pattern, string)
if match:
process(match)
匹配对象支持以下方法和属性:
Match.expand
(template)
对 template 进行反斜杠转义替换并且返回,就像 sub()
方法中一样。转义如同 \n
被转换成合适的字符,数字引用(\1
, \2
)和命名组合(\g<1>
, \g<name>
) 替换为相应组合的内容。
在 3.5 版更改: 不匹配的组合替换为空字符串。
Match.group
([group1, …])
返回一个或者多个匹配的子组。如果只有一个参数,结果就是一个字符串,如果有多个参数,结果就是一个元组(每个参数对应一个项),如果没有参数,组1默认到0(整个匹配都被返回)。 如果一个组N 参数值为 0,相应的返回值就是整个匹配字符串;如果它是一个范围 [1..99],结果就是相应的括号组字符串。如果一个组号是负数,或者大于样式中定义的组数,就引发一个 IndexError
异常。如果一个组包含在样式的一部分,并被匹配多次,就返回最后一个匹配。:
>>> m = re.match(r"(\w+) (\w+)", "Isaac Newton, physicist")
>>> m.group(0) # The entire match
'Isaac Newton'
>>> m.group(1) # The first parenthesized subgroup.
'Isaac'
>>> m.group(2) # The second parenthesized subgroup.
'Newton'
>>> m.group(1, 2) # Multiple arguments give us a tuple.
('Isaac', 'Newton')
如果正则表达式使用了 (?P<name>...)
语法, groupN 参数就也可能是命名组合的名字。如果一个字符串参数在样式中未定义为组合名,就引发一个 IndexError
异常。
一个相对复杂的例子
>>> m = re.match(r"(?P<first_name>\w+) (?P<last_name>\w+)", "Malcolm Reynolds")
>>> m.group('first_name')
'Malcolm'
>>> m.group('last_name')
'Reynolds'
命名组合同样可以通过索引值引用
>>> m.group(1)
'Malcolm'
>>> m.group(2)
'Reynolds'
如果一个组匹配成功多次,就只返回最后一个匹配
>>> m = re.match(r"(..)+", "a1b2c3") # Matches 3 times.
>>> m.group(1) # Returns only the last match.
'c3'
Match.__getitem__
(g)
这个等价于 m.group(g)
。这允许更方便的引用一个匹配
>>> m = re.match(r"(\w+) (\w+)", "Isaac Newton, physicist")
>>> m[0] # The entire match
'Isaac Newton'
>>> m[1] # The first parenthesized subgroup.
'Isaac'
>>> m[2] # The second parenthesized subgroup.
'Newton'
3.6 新版功能.
Match.groups
(default=None)
返回一个元组,包含所有匹配的子组,在样式中出现的从1到任意多的组合。 default 参数用于不参与匹配的情况,默认为 None
。
例如:
>>> m = re.match(r"(\d+)\.(\d+)", "24.1632")
>>> m.groups()
('24', '1632')
如果我们使小数点可选,那么不是所有的组都会参与到匹配当中。这些组合默认会返回一个 None
,除非指定了 default 参数。
>>> m = re.match(r"(\d+)\.?(\d+)?", "24")
>>> m.groups() # Second group defaults to None.
('24', None)
>>> m.groups('0') # Now, the second group defaults to '0'.
('24', '0')
Match.groupdict
(default=None)
返回一个字典,包含了所有的 命名 子组。key就是组名。 default 参数用于不参与匹配的组合;默认为 None
。 例如
>>> m = re.match(r"(?P<first_name>\w+) (?P<last_name>\w+)", "Malcolm Reynolds")
>>> m.groupdict()
{'first_name': 'Malcolm', 'last_name': 'Reynolds'}
Match.start
([group])
Match.end
([group])
返回 group 匹配到的字串的开始和结束标号。group 默认为0(意思是整个匹配的子串)。如果 group 存在,但未产生匹配,就返回 -1
。对于一个匹配对象 m, 和一个未参与匹配的组 g ,组 g (等价于 m.group(g)
)产生的匹配是
m.string[m.start(g):m.end(g)]
注意 m.start(group)
将会等于 m.end(group)
,如果 group 匹配一个空字符串的话。比如,在 m = re.search('b(c?)', 'cba')
之后,m.start(0)
为 1, m.end(0)
为 2, m.start(1)
和 m.end(1)
都是 2, m.start(2)
引发一个 IndexError
异常。
这个例子会从email地址中移除掉 remove_this
>>> email = "tony@tiremove_thisger.net"
>>> m = re.search("remove_this", email)
>>> email[:m.start()] + email[m.end():]
'tony@tiger.net'
Match.span
([group])
对于一个匹配 m , 返回一个二元组 (m.start(group), m.end(group))
。 注意如果 group 没有在这个匹配中,就返回 (-1, -1)
。group 默认为0,就是整个匹配。
Match.pos
pos 的值,会传递给 search()
或 match()
的方法 a 正则对象 。这个是正则引擎开始在字符串搜索一个匹配的索引位置。
Match.endpos
endpos 的值,会传递给 search()
或 match()
的方法 a 正则对象 。这个是正则引擎停止在字符串搜索一个匹配的索引位置。
Match.lastindex
捕获组的最后一个匹配的整数索引值,或者 None
如果没有匹配产生的话。比如,对于字符串 'ab'
,表达式 (a)b
, ((a)(b))
, 和 ((ab))
将得到 lastindex == 1
, 而 (a)(b)
会得到 lastindex == 2
。
Match.lastgroup
最后一个匹配的命名组名字,或者 None
如果没有产生匹配的话。
Match.re
返回产生这个实例的 正则对象 , 这个实例是由 正则对象的 match()
或 search()
方法产生的。
Match.string
传递到 match()
或 search()
的字符串。
在 3.7 版更改: 添加了对 copy.copy()
和 copy.deepcopy()
的支持。匹配对象被看作是原子性的。
正则表达式例子
检查对子
在这个例子里,我们使用以下辅助函数来更好地显示匹配对象:
def displaymatch(match):
if match is None:
return None
return '<Match: %r, groups=%r>' % (match.group(), match.groups())
假设你在写一个扑克程序,一个玩家的一手牌为五个字符的串,每个字符表示一张牌,”a” 就是 A, “k” K, “q” Q, “j” J, “t” 为 10, “2” 到 “9” 表示2 到 9。
要看给定的字符串是否有效,我们可以按照以下步骤
>>> valid = re.compile(r"^[a2-9tjqk]{5}$")
>>> displaymatch(valid.match("akt5q")) # Valid.
"<Match: 'akt5q', groups=()>"
>>> displaymatch(valid.match("akt5e")) # Invalid.
>>> displaymatch(valid.match("akt")) # Invalid.
>>> displaymatch(valid.match("727ak")) # Valid.
"<Match: '727ak', groups=()>"
最后一手牌,"727ak"
,包含了一个对子,或者两张同样数值的牌。要用正则表达式匹配它,应该使用向后引用如下
>>> pair = re.compile(r".*(.).*\1")
>>> displaymatch(pair.match("717ak")) # Pair of 7s.
"<Match: '717', groups=('7',)>"
>>> displaymatch(pair.match("718ak")) # No pairs.
>>> displaymatch(pair.match("354aa")) # Pair of aces.
"<Match: '354aa', groups=('a',)>"
要找出对子由什么牌组成,开发者可以按照下面的方式来使用匹配对象的 group()
方法:
>>> pair = re.compile(r".*(.).*\1")
>>> pair.match("717ak").group(1)
'7'
# Error because re.match() returns None, which doesn't have a group() method:
>>> pair.match("718ak").group(1)
Traceback (most recent call last):
File "<pyshell#23>", line 1, in <module>
re.match(r".*(.).*\1", "718ak").group(1)
AttributeError: 'NoneType' object has no attribute 'group'
>>> pair.match("354aa").group(1)
'a'
模拟 scanf()
Python 目前没有一个类似c函数 scanf()
的替代品。正则表达式通常比 scanf()
格式字符串要更强大一些,但也带来更多复杂性。下面的表格提供了 scanf()
格式符和正则表达式大致相同的映射。
scanf() 格式符 |
正则表达式 |
---|---|
%c |
. |
%5c |
.{5} |
%d |
[-+]?\d+ |
%e , %E , %f , %g |
`[-+]?(\d+(.\d*)? |
%i |
`[-+]?(0[xX][\dA-Fa-f]+ |
%o |
[-+]?[0-7]+ |
%s |
\S+ |
%u |
\d+ |
%x , %X |
[-+]?(0[xX])?[\dA-Fa-f]+ |
从文件名和数字提取字符串
/usr/sbin/sendmail - 0 errors, 4 warnings
你可以使用 scanf()
格式化
%s - %d errors, %d warnings
等价的正则表达式是:
(\S+) - (\d+) errors, (\d+) warnings
search() vs. match()
Python 提供了两种不同的操作:基于 re.match()
检查字符串开头,或者 re.search()
检查字符串的任意位置(默认Perl中的行为)。
例如:
>>> re.match("c", "abcdef") # No match
>>> re.search("c", "abcdef") # Match
<re.Match object; span=(2, 3), match='c'>
在 search()
中,可以用 '^'
作为开始来限制匹配到字符串的首位
>>> re.match("c", "abcdef") # No match
>>> re.search("^c", "abcdef") # No match
>>> re.search("^a", "abcdef") # Match
<re.Match object; span=(0, 1), match='a'>
注意 MULTILINE
多行模式中函数 match()
只匹配字符串的开始,但使用 search()
和以 '^'
开始的正则表达式会匹配每行的开始
>>> re.match('X', 'A\nB\nX', re.MULTILINE) # No match
>>> re.search('^X', 'A\nB\nX', re.MULTILINE) # Match
<re.Match object; span=(4, 5), match='X'>
制作一个电话本
split()
将字符串用参数传递的样式分隔开。这个方法对于转换文本数据到易读而且容易修改的数据结构,是很有用的,如下面的例子证明。
首先,这里是输入。 它通常来自一个文件,这里我们使用三重引号字符串语法
>>> text = """Ross McFluff: 834.345.1254 155 Elm Street
...
... Ronald Heathmore: 892.345.3428 436 Finley Avenue
... Frank Burger: 925.541.7625 662 South Dogwood Way
...
...
... Heather Albrecht: 548.326.4584 919 Park Place"""
条目用一个或者多个换行符分开。现在我们将字符串转换为一个列表,每个非空行都有一个条目:
>>> entries = re.split("\n+", text)
>>> entries
['Ross McFluff: 834.345.1254 155 Elm Street',
'Ronald Heathmore: 892.345.3428 436 Finley Avenue',
'Frank Burger: 925.541.7625 662 South Dogwood Way',
'Heather Albrecht: 548.326.4584 919 Park Place']
最终,将每个条目分割为一个由名字、姓氏、电话号码和地址组成的列表。我们为 split()
使用了 maxsplit
形参,因为地址中包含有被我们作为分割模式的空格符:
>>> [re.split(":? ", entry, 3) for entry in entries]
[['Ross', 'McFluff', '834.345.1254', '155 Elm Street'],
['Ronald', 'Heathmore', '892.345.3428', '436 Finley Avenue'],
['Frank', 'Burger', '925.541.7625', '662 South Dogwood Way'],
['Heather', 'Albrecht', '548.326.4584', '919 Park Place']]
:?
样式匹配姓后面的冒号,因此它不出现在结果列表中。如果 maxsplit
设置为 4
,我们还可以从地址中获取到房间号:
>>> [re.split(":? ", entry, 4) for entry in entries]
[['Ross', 'McFluff', '834.345.1254', '155', 'Elm Street'],
['Ronald', 'Heathmore', '892.345.3428', '436', 'Finley Avenue'],
['Frank', 'Burger', '925.541.7625', '662', 'South Dogwood Way'],
['Heather', 'Albrecht', '548.326.4584', '919', 'Park Place']]
文字整理
sub()
替换字符串中出现的样式的每一个实例。这个例子证明了使用 sub()
来整理文字,或者随机化每个字符的位置,除了首位和末尾字符
>>> def repl(m):
... inner_word = list(m.group(2))
... random.shuffle(inner_word)
... return m.group(1) + "".join(inner_word) + m.group(3)
>>> text = "Professor Abdolmalek, please report your absences promptly."
>>> re.sub(r"(\w)(\w+)(\w)", repl, text)
'Poefsrosr Aealmlobdk, pslaee reorpt your abnseces plmrptoy.'
>>> re.sub(r"(\w)(\w+)(\w)", repl, text)
'Pofsroser Aodlambelk, plasee reoprt yuor asnebces potlmrpy.'
查找所有副词
findall()
匹配样式 所有 的出现,不仅是像 search()
中的第一个匹配。比如,如果一个作者希望找到文字中的所有副词,他可能会按照以下方法用 findall()
>>> text = "He was carefully disguised but captured quickly by police."
>>> re.findall(r"\w+ly", text)
['carefully', 'quickly']
查找所有的副词及其位置
如果需要匹配样式的更多信息, finditer()
可以起到作用,它提供了 匹配对象 作为返回值,而不是字符串。继续上面的例子,如果一个作者希望找到所有副词和它的位置,可以按照下面方法使用 finditer()
>>> text = "He was carefully disguised but captured quickly by police."
>>> for m in re.finditer(r"\w+ly", text):
... print('%02d-%02d: %s' % (m.start(), m.end(), m.group(0)))
07-16: carefully
40-47: quickly
原始字符串标记
原始字符串记法 (r"text"
) 保持正则表达式正常。否则,每个正则式里的反斜杠('\'
) 都必须前缀一个反斜杠来转义。比如,下面两行代码功能就是完全一致的
>>> re.match(r"\W(.)\1\W", " ff ")
<re.Match object; span=(0, 4), match=' ff '>
>>> re.match("\\W(.)\\1\\W", " ff ")
<re.Match object; span=(0, 4), match=' ff '>
当需要匹配一个字符反斜杠,它必须在正则表达式中转义。在原始字符串记法,就是 r"\\"
。否则就必须用 "\\\\"
,来表示同样的意思
>>> re.match(r"\\", r"\\")
<re.Match object; span=(0, 1), match='\\'>
>>> re.match("\\\\", r"\\")
<re.Match object; span=(0, 1), match='\\'>
写一个词法分析器
一个 词法器或词法分析器 分析字符串,并分类成目录组。 这是写一个编译器或解释器的第一步。
文字目录是由正则表达式指定的。这个技术是通过将这些样式合并为一个主正则式,并且循环匹配来实现的
from typing import NamedTuple
import re
class Token(NamedTuple):
type: str
value: str
line: int
column: int
def tokenize(code):
keywords = {'IF', 'THEN', 'ENDIF', 'FOR', 'NEXT', 'GOSUB', 'RETURN'}
token_specification = [
('NUMBER', r'\d+(\.\d*)?'), # Integer or decimal number
('ASSIGN', r':='), # Assignment operator
('END', r';'), # Statement terminator
('ID', r'[A-Za-z]+'), # Identifiers
('OP', r'[+\-*/]'), # Arithmetic operators
('NEWLINE', r'\n'), # Line endings
('SKIP', r'[ \t]+'), # Skip over spaces and tabs
('MISMATCH', r'.'), # Any other character
]
tok_regex = '|'.join('(?P<%s>%s)' % pair for pair in token_specification)
line_num = 1
line_start = 0
for mo in re.finditer(tok_regex, code):
kind = mo.lastgroup
value = mo.group()
column = mo.start() - line_start
if kind == 'NUMBER':
value = float(value) if '.' in value else int(value)
elif kind == 'ID' and value in keywords:
kind = value
elif kind == 'NEWLINE':
line_start = mo.end()
line_num += 1
continue
elif kind == 'SKIP':
continue
elif kind == 'MISMATCH':
raise RuntimeError(f'{value!r} unexpected on line {line_num}')
yield Token(kind, value, line_num, column)
statements = '''
IF quantity THEN
total := total + price * quantity;
tax := price * 0.05;
ENDIF;
'''
for token in tokenize(statements):
print(token)
该词法器产生以下的输出
Token(type='IF', value='IF', line=2, column=4)
Token(type='ID', value='quantity', line=2, column=7)
Token(type='THEN', value='THEN', line=2, column=16)
Token(type='ID', value='total', line=3, column=8)
Token(type='ASSIGN', value=':=', line=3, column=14)
Token(type='ID', value='total', line=3, column=17)
Token(type='OP', value='+', line=3, column=23)
Token(type='ID', value='price', line=3, column=25)
Token(type='OP', value='*', line=3, column=31)
Token(type='ID', value='quantity', line=3, column=33)
Token(type='END', value=';', line=3, column=41)
Token(type='ID', value='tax', line=4, column=8)
Token(type='ASSIGN', value=':=', line=4, column=12)
Token(type='ID', value='price', line=4, column=15)
Token(type='OP', value='*', line=4, column=21)
Token(type='NUMBER', value=0.05, line=4, column=23)
Token(type='END', value=';', line=4, column=27)
Token(type='ENDIF', value='ENDIF', line=5, column=4)
Token(type='END', value=';', line=5, column=9)
Frie09
Friedl, Jeffrey. Mastering Regular Expressions. 3rd ed., O’Reilly Media, 2009. 该书的第三版不再包含 Python,但第一版极详细地覆盖了正则表达式模式串的编写。
difflib
—- 计算差异的辅助工具
源代码: Lib/difflib.py
此模块提供用于比较序列的类和函数。 例如,它可被用于比较文件,并可产生多种格式的不同文件差异信息,包括 HTML 和上下文以及统一的 diff 数据。
class difflib.SequenceMatcher
这是一个灵活的类,可用于比较任何类型的序列对,只要序列元素为 hashable 对象。 其基本算法要早于由 Ratcliff 和 Obershelp 于 1980 年代末期发表并以“格式塔模式匹配”的夸张名称命名的算法,并且更加有趣一些。 其思路是找到不包含“垃圾”元素的最长连续匹配子序列;所谓“垃圾”元素是指其在某种意义上没有价值,例如空白行或空白符。 (处理垃圾元素是对 Ratcliff 和 Obershelp 算法的一个扩展。) 然后同样的思路将递归地应用于匹配序列的左右序列片段。 这并不能产生最小编辑序列,但确实能产生在人们看来“正确”的匹配。
耗时: 基本 Ratcliff-Obershelp 算法在最坏情况下为立方时间而在一般情况下为平方时间。 SequenceMatcher
在最坏情况下为平方时间而在一般情况下的行为受到序列中有多少相同元素这一因素的微妙影响;在最佳情况下则为线性时间。
自动垃圾启发式计算: SequenceMatcher
支持使用启发式计算来自动将特定序列项视为垃圾。 这种启发式计算会统计每个单独项在序列中出现的次数。 如果某一项(在第一项之后)的重复次数超过序列长度的 1% 并且序列长度至少有 200 项,该项会被标记为“热门”并被视为序列匹配中的垃圾。 这种启发式计算可以通过在创建 SequenceMatcher
时将 autojunk
参数设为 False
来关闭。
3.2 新版功能: autojunk 形参。
class difflib.Differ
这个类的作用是比较由文本行组成的序列,并产生可供人阅读的差异或增量信息。 Differ 统一使用 SequenceMatcher
来完成行序列的比较以及相似(接近匹配)行内部字符序列的比较。
Differ
增量的每一行均以双字母代码打头:
双字母代码 | 含意 |
---|---|
‘- ‘ |
行为序列 1 所独有 |
‘+ ‘ |
行为序列 2 所独有 |
‘ ‘ |
行在两序列中相同 |
‘? ‘ |
行不存在于任一输入序列 |
以 ‘?
‘ 打头的行尝试将视线引至行以外而不存在于任一输入序列的差异。 如果序列包含制表符则这些行可能会令人感到迷惑。
class difflib.HtmlDiff
这个类可用于创建 HTML 表格(或包含表格的完整 HTML 文件)以并排地逐行显示文本比较,行间与行外的更改将突出显示。 此表格可以基于完全或上下文差异模式来生成。
这个类的构造函数:
__init__
(tabsize=8, wrapcolumn=None, linejunk=None, charjunk=IS_CHARACTER_JUNK)初始化
HtmlDiff
的实例。tabsize 是一个可选关键字参数,指定制表位的间隔,默认值为
8
。wrapcolumn 是一个可选关键字参数,指定行文本自动打断并换行的列位置,默认值为
None
表示不自动换行。linejunk 和 charjunk 均是可选关键字参数,会传入
ndiff()
(被HtmlDiff
用来生成并排显示的 HTML 差异)。
下列是公开的方法
make_file
(fromlines, tolines, fromdesc=’’, todesc=’’, context=False, numlines=5, **, charset=’utf-8’*)比较 fromlines 和 tolines (字符串列表) 并返回一个字符串,表示一个完整 HTML 文件,其中包含各行差异的表格,行间与行外的更改将突出显示。
fromdesc 和 todesc 均是可选关键字参数,指定来源/目标文件的列标题字符串(默认均为空白字符串)。
context 和 numlines 均是可选关键字参数。 当只要显示上下文差异时就将 context 设为
True
,否则默认值False
为显示完整文件。 numlines 默认为5
。 当 context 为True
时 numlines 将控制围绕突出显示差异部分的上下文行数。 当 context 为False
时 numlines 将控制在使用 “next” 超链接时突出显示差异部分之前所显示的行数(设为零则会导致 “next” 超链接将下一个突出显示差异部分放在浏览器顶端,不添加任何前导上下文)。注解
fromdesc 和 todesc 会被当作未转义的 HTML 来解读,当接收不可信来源的输入时应该适当地进行转义。
在 3.5 版更改: 增加了 charset 关键字参数。 HTML 文档的默认字符集从
'ISO-8859-1'
更改为'utf-8'
。make_table
(fromlines, tolines, fromdesc=’’, todesc=’’, context=False, numlines=5)比较 fromlines 和 tolines (字符串列表) 并返回一个字符串,表示一个包含各行差异的完整 HTML 表格,行间与行外的更改将突出显示。
Tools/scripts/diff.py
是这个类的命令行前端,其中包含一个很好的使用示例。
difflib.context_diff
(a, b, fromfile=’’, tofile=’’, fromfiledate=’’, tofiledate=’’, n=3, lineterm=’\n’)
比较 a 和 b (字符串列表);返回上下文差异格式的增量信息 (一个产生增量行的 generator)。
所谓上下文差异是一种只显示有更改的行再加几个上下文行的紧凑形式。 更改被显示为之前/之后的样式。 上下文行数由 n 设定,默认为三行。
默认情况下,差异控制行(以 ***
or ---
表示)是通过末尾换行符来创建的。 这样做的好处是从 io.IOBase.readlines()
创建的输入将得到适用于 io.IOBase.writelines()
的差异信息,因为输入和输出都带有末尾换行符。
对于没有末尾换行符的输入,应将 lineterm 参数设为 ""
,这样输出内容将统一不带换行符。
上下文差异格式通常带有一个记录文件名和修改时间的标头。 这些信息的部分或全部可以使用字符串 fromfile, tofile, fromfiledate 和 tofiledate 来指定。 修改时间通常以 ISO 8601 格式表示。 如果未指定,这些字符串默认为空。
>>> s1 = ['bacon\n', 'eggs\n', 'ham\n', 'guido\n']
>>> s2 = ['python\n', 'eggy\n', 'hamster\n', 'guido\n']
>>> sys.stdout.writelines(context_diff(s1, s2, fromfile='before.py', tofile='after.py'))
*** before.py
--- after.py
***************
*** 1,4 ****
! bacon
! eggs
! ham
guido
--- 1,4 ----
! python
! eggy
! hamster
guido
difflib.get_close_matches
(word, possibilities, n=3, cutoff=0.6)
返回由最佳“近似”匹配构成的列表。 word 为一个指定目标近似匹配的序列(通常为字符串),possibilities 为一个由用于匹配 word 的序列构成的列表(通常为字符串列表)。
可选参数 n (默认为 3
) 指定最多返回多少个近似匹配; n 必须大于 0
.
可选参数 cutoff (默认为 0.6
) 是一个 [0, 1] 范围内的浮点数。 与 word 相似度得分未达到该值的候选匹配将被忽略。
候选匹配中(不超过 n 个)的最佳匹配将以列表形式返回,按相似度得分排序,最相似的排在最前面。
>>> get_close_matches('appel', ['ape', 'apple', 'peach', 'puppy'])
['apple', 'ape']
>>> import keyword
>>> get_close_matches('wheel', keyword.kwlist)
['while']
>>> get_close_matches('pineapple', keyword.kwlist)
[]
>>> get_close_matches('accept', keyword.kwlist)
['except']
difflib.ndiff
(a, b, linejunk=None, charjunk=IS_CHARACTER_JUNK)
比较 a 和 b (字符串列表);返回 Differ
形式的增量信息 (一个产生增量行的 generator)。
可选关键字形参 linejunk 和 charjunk 均为过滤函数 (或为 None
):
linejunk: 此函数接受单个字符串参数,如果其为垃圾字符串则返回真值,否则返回假值。 默认为 None
。 此外还有一个模块层级的函数 IS_LINE_JUNK()
,它会过滤掉没有可见字符的行,除非该行添加了至多一个井号符 ('#'
) — 但是下层的 SequenceMatcher
类会动态分析哪些行的重复频繁到足以形成噪音,这通常会比使用此函数的效果更好。
charjunk: 此函数接受一个字符(长度为 1 的字符串),如果其为垃圾字符则返回真值,否则返回假值。 默认为模块层级的函数 IS_CHARACTER_JUNK()
,它会过滤掉空白字符(空格符或制表符;但包含换行符可不是个好主意!)。
Tools/scripts/ndiff.py
是这个函数的命令行前端。
>>> diff = ndiff('one\ntwo\nthree\n'.splitlines(keepends=True),
... 'ore\ntree\nemu\n'.splitlines(keepends=True))
>>> print(''.join(diff), end="")
- one
? ^
+ ore
? ^
- two
- three
? -
+ tree
+ emu
difflib.restore
(sequence, which)
返回两个序列中产生增量的那一个。
给出一个由 Differ.compare()
或 ndiff()
产生的 序列,提取出来自文件 1 或 2 (which 形参) 的行,去除行前缀。
示例:
>>> diff = ndiff('one\ntwo\nthree\n'.splitlines(keepends=True),
... 'ore\ntree\nemu\n'.splitlines(keepends=True))
>>> diff = list(diff) # materialize the generated delta into a list
>>> print(''.join(restore(diff, 1)), end="")
one
two
three
>>> print(''.join(restore(diff, 2)), end="")
ore
tree
emu
difflib.unified_diff
(a, b, fromfile=’’, tofile=’’, fromfiledate=’’, tofiledate=’’, n=3, lineterm=’\n’)
比较 a 和 b (字符串列表);返回统一差异格式的增量信息 (一个产生增量行的 generator)。
所以统一差异是一种只显示有更改的行再加几个上下文行的紧凑形式。 更改被显示为内联的样式(而不是分开的之前/之后文本块)。 上下文行数由 n 设定,默认为三行。
默认情况下,差异控制行 (以 ---
, +++
或 @@
表示) 是通过末尾换行符来创建的。 这样做的好处是从 io.IOBase.readlines()
创建的输入将得到适用于 io.IOBase.writelines()
的差异信息,因为输入和输出都带有末尾换行符。
对于没有末尾换行符的输入,应将 lineterm 参数设为 ""
,这样输出内容将统一不带换行符。
上下文差异格式通常带有一个记录文件名和修改时间的标头。 这些信息的部分或全部可以使用字符串 fromfile, tofile, fromfiledate 和 tofiledate 来指定。 修改时间通常以 ISO 8601 格式表示。 如果未指定,这些字符串默认为空。
>>> s1 = ['bacon\n', 'eggs\n', 'ham\n', 'guido\n']
>>> s2 = ['python\n', 'eggy\n', 'hamster\n', 'guido\n']
>>> sys.stdout.writelines(unified_diff(s1, s2, fromfile='before.py', tofile='after.py'))
--- before.py
+++ after.py
@@ -1,4 +1,4 @@
-bacon
-eggs
-ham
+python
+eggy
+hamster
guido
difflib.diff_bytes
(dfunc, a, b, fromfile=b’’, tofile=b’’, fromfiledate=b’’, tofiledate=b’’, n=3, lineterm=b’\n’)
使用 dfunc 比较 a 和 b (字节串对象列表);产生以 dfunc 所返回格式表示的差异行列表(也是字节串)。 dfunc 必须是可调用对象,通常为 unified_diff()
或 context_diff()
。
允许你比较编码未知或不一致的数据。 除 n 之外的所有输入都必须为字节串对象而非字符串。 作用方式为无损地将所有输入 (除 n 之外) 转换为字符串,并调用 dfunc(a, b, fromfile, tofile, fromfiledate, tofiledate, n, lineterm)
。 dfunc 的输出会被随即转换回字节串,这样你所得到的增量行将具有与 a 和 b 相同的未知/不一致编码。
3.5 新版功能.
difflib.IS_LINE_JUNK
(line)
对于可忽略的行返回 True
。 如果 line 为空行或只包含单个 '#'
则 line 行就是可忽略的,否则就是不可忽略的。 此函数被用作较旧版本 ndiff()
中 linejunk 形参的默认值。
difflib.IS_CHARACTER_JUNK
(ch)
对于可忽略的字符返回 True
。 字符 ch 如果为空格符或制表符则 ch 就是可忽略的,否则就是不可忽略的。 此函数被用作 ndiff()
中 charjunk 形参的默认值。
SequenceMatcher 对象
SequenceMatcher
类具有这样的构造器:
class difflib.SequenceMatcher
(isjunk=None, a=’’, b=’’, autojunk=True)
可选参数 isjunk 必须为 None
(默认值) 或为接受一个序列元素并当且仅当其为应忽略的“垃圾”元素时返回真值的单参数函数。 传入 None
作为 isjunk 的值就相当于传入 lambda x: False
;也就是说不忽略任何值。 例如,传入:
lambda x: x in " \t"
如果你以字符序列的形式对行进行比较,并且不希望区分空格符或硬制表符。
可选参数 a 和 b 为要比较的序列;两者默认为空字符串。 两个序列的元素都必须为 hashable。
可选参数 autojunk 可用于启用自动垃圾启发式计算。
3.2 新版功能: autojunk 形参。
SequenceMatcher 对象接受三个数据属性: bjunk 是 b 当中 isjunk 为 True
的元素集合;bpopular 是被启发式计算(如果其未被禁用)视为热门候选的非垃圾元素集合;b2j 是将 b 当中剩余元素映射到一个它们出现位置列表的字典。 所有三个数据属性将在 b 通过 set_seqs()
或 set_seq2()
重置时被重置。
3.2 新版功能: bjunk 和 bpopular 属性。
SequenceMatcher
对象具有以下方法:
set_seqs
(a, b)设置要比较的两个序列。
SequenceMatcher
计算并缓存有关第二个序列的详细信息,这样如果你想要将一个序列与多个序列进行比较,可使用 set_seq2()
一次性地设置该常用序列并重复地对每个其他序列各调用一次 set_seq1()
。
set_seq1
(a)设置要比较的第一个序列。 要比较的第二个序列不会改变。
set_seq2
(b)设置要比较的第二个序列。 要比较的第一个序列不会改变。
find_longest_match
(alo=0, ahi=None, blo=0, bhi=None)找出
a[alo:ahi]
和b[blo:bhi]
中的最长匹配块。如果 isjunk 被省略或为
None
,find_longest_match()
将返回(i, j, k)
使得a[i:i+k]
等于b[j:j+k]
,其中alo <= i <= i+k <= ahi
并且blo <= j <= j+k <= bhi
。 对于所有满足这些条件的(i', j', k')
,如果i == i'
,j <= j'
也被满足,则附加条件k >= k'
,i <= i'
。 换句话说,对于所有最长匹配块,返回在 a 当中最先出现的一个,而对于在 a 当中最先出现的所有最长匹配块,则返回在 b 当中最先出现的一个。>>> s = SequenceMatcher(None, " abcd", "abcd abcd") >>> s.find_longest_match(0, 5, 0, 9) Match(a=0, b=4, size=5)
如果提供了 isjunk,将按上述规则确定第一个最长匹配块,但额外附加不允许块内出现垃圾元素的限制。 然后将通过(仅)匹配两边的垃圾元素来尽可能地扩展该块。 这样结果块绝对不会匹配垃圾元素,除非同样的垃圾元素正好与有意义的匹配相邻。
这是与之前相同的例子,但是将空格符视为垃圾。 这将防止
' abcd'
直接与第二个序列末尾的' abcd'
相匹配。 而只可以匹配'abcd'
,并且是匹配第二个序列最左边的'abcd'
:>>> s = SequenceMatcher(lambda x: x==" ", " abcd", "abcd abcd") >>> s.find_longest_match(0, 5, 0, 9) Match(a=1, b=0, size=4)
如果未找到匹配块,此方法将返回
(alo, blo, 0)
。此方法将返回一个 named tuple
Match(a, b, size)
。在 3.9 版更改: 加入默认参数。
get_matching_blocks
()返回描述非重叠匹配子序列的三元组列表。 每个三元组的形式为
(i, j, n)
,其含义为a[i:i+n] == b[j:j+n]
。 这些三元组按 i 和 j 单调递增排列。最后一个三元组用于占位,其值为
(len(a), len(b), 0)
。 它是唯一n == 0
的三元组。 如果(i, j, n)
和(i', j', n')
是在列表中相邻的三元组,且后者不是列表中的最后一个三元组,则i+n < i'
或j+n < j'
;换句话说,相邻的三元组总是描述非相邻的相等块。>>> s = SequenceMatcher(None, "abxcd", "abcd") >>> s.get_matching_blocks() [Match(a=0, b=0, size=2), Match(a=3, b=2, size=2), Match(a=5, b=4, size=0)]
get_opcodes
()返回描述如何将 a 变为 b 的 5 元组列表,每个元组的形式为
(tag, i1, i2, j1, j2)
。 在第一个元组中i1 == j1 == 0
,而在其余的元组中 i1 等于前一个元组的 i2*,并且 *j1 也等于前一个元组的 j2。tag 值为字符串,其含义如下:
值 含意 ‘replace’
a[i1:i2]
应由b[j1:j2]
替换。‘delete’
a[i1:i2]
应被删除。 请注意在此情况下j1 == j2
。‘insert’
b[j1:j2]
应插入到a[i1:i1]
。 请注意在此情况下i1 == i2
。‘equal’
a[i1:i2] == b[j1:j2]
(两个子序列相同)。例如:
>>> a = "qabxcd" >>> b = "abycdf" >>> s = SequenceMatcher(None, a, b) >>> for tag, i1, i2, j1, j2 in s.get_opcodes(): ... print('{:7} a[{}:{}] --> b[{}:{}] {!r:>8} --> {!r}'.format( ... tag, i1, i2, j1, j2, a[i1:i2], b[j1:j2])) delete a[0:1] --> b[0:0] 'q' --> '' equal a[1:3] --> b[0:2] 'ab' --> 'ab' replace a[3:4] --> b[2:3] 'x' --> 'y' equal a[4:6] --> b[3:5] 'cd' --> 'cd' insert a[6:6] --> b[5:6] '' --> 'f'
get_grouped_opcodes
(n=3)返回一个带有最多 n 行上下文的分组的 generator。
从
get_opcodes()
所返回的组开始,此方法会拆分出较小的更改簇并消除没有更改的间隔区域。这些分组以与
get_opcodes()
相同的格式返回。ratio
()返回一个取值范围 [0, 1] 的浮点数作为序列相似性度量。
其中 T 是两个序列中元素的总数量,M 是匹配的数量,即 2.0*M / T。 请注意如果两个序列完全相同则该值为
1.0
,如果两者完全不同则为0.0
。如果
get_matching_blocks()
或get_opcodes()
尚未被调用则此方法运算消耗较大,在此情况下你可能需要先调用quick_ratio()
或real_quick_ratio()
来获取一个上界。注解
注意:
ratio()
调用的结果可能会取决于参数的顺序。 例如:>>> SequenceMatcher(None, 'tide', 'diet').ratio() 0.25 >>> SequenceMatcher(None, 'diet', 'tide').ratio() 0.5
quick_ratio
()相对快速地返回一个
ratio()
的上界。real_quick_ratio
()非常快速地返回一个
ratio()
的上界。
这三个返回匹配部分占字符总数的比率的方法可能由于不同的近似级别而给出不一样的结果,但是 quick_ratio()
和 real_quick_ratio()
总是会至少与 ratio()
一样大:
>>> s = SequenceMatcher(None, "abcd", "bcde")
>>> s.ratio()
0.75
>>> s.quick_ratio()
0.75
>>> s.real_quick_ratio()
1.0
SequenceMatcher 的示例
以下示例比较两个字符串,并将空格视为“垃圾”:
>>> s = SequenceMatcher(lambda x: x == " ",
... "private Thread currentThread;",
... "private volatile Thread currentThread;")
ratio()
返回一个 [0, 1] 范围内的整数作为两个序列相似性的度量。 根据经验,ratio()
值超过 0.6 就意味着两个序列是近似匹配的:
>>> print(round(s.ratio(), 3))
0.866
如果你只对两个序列相匹配的位置感兴趣,则 get_matching_blocks()
就很方便:
>>> for block in s.get_matching_blocks():
... print("a[%d] and b[%d] match for %d elements" % block)
a[0] and b[0] match for 8 elements
a[8] and b[17] match for 21 elements
a[29] and b[38] match for 0 elements
请注意 get_matching_blocks()
返回的最后一个元组总是只用于占位的 (len(a), len(b), 0)
,这也是元组末尾元素(匹配的元素数量)为 0
的唯一情况。
如果你想要知道如何将第一个序列转成第二个序列,可以使用 get_opcodes()
:
>>> for opcode in s.get_opcodes():
... print("%6s a[%d:%d] b[%d:%d]" % opcode)
equal a[0:8] b[0:8]
insert a[8:8] b[8:17]
equal a[8:29] b[17:38]
参见
- 此模块中的
get_close_matches()
函数显示了如何基于SequenceMatcher
构建简单的代码来执行有用的功能。 - 使用
SequenceMatcher
构建小型应用的 简易版本控制方案。
Differ 对象
请注意 Differ
所生成的增量并不保证是 最小 差异。 相反,最小差异往往是违反直觉的,因为它们会同步任何可能的地方,有时甚至意外产生相距 100 页的匹配。 将同步点限制为连续匹配保留了一些局部性概念,这偶尔会带来产生更长差异的代价。
Differ
类具有这样的构造器:
class difflib.Differ
(linejunk=None, charjunk=None)
可选关键字形参 linejunk 和 charjunk 均为过滤函数 (或为 None
):
linejunk: 接受单个字符串作为参数的函数,如果其为垃圾字符串则返回真值。 默认值为 None
,意味着没有任何行会被视为垃圾行。
charjunk: 接受单个字符(长度为 1 的字符串)作为参数的函数,如果其为垃圾字符则返回真值。 默认值为 None
,意味着没有任何字符会被视为垃圾字符。
这些垃圾过滤函数可加快查找差异的匹配速度,并且不会导致任何差异行或字符被忽略。
Differ
对象是通过一个单独方法来使用(生成增量)的:
compare
(a, b)比较两个由行组成的序列,并生成增量(一个由行组成的序列)。
每个序列必须包含一个以换行符结尾的单行字符串。 这样的序列可以通过文件类对象的
readlines()
方法来获取。 所生成的增量同样由以换行符结尾的字符串构成,可以通过文件类对象的writelines()
方法原样打印出来。
Differ 示例
此示例比较两段文本。 首先我们设置文本为以换行符结尾的单行字符串构成的序列(这样的序列也可以通过文件类对象的 readlines()
方法来获取):
>>> text1 = ''' 1. Beautiful is better than ugly.
... 2. Explicit is better than implicit.
... 3. Simple is better than complex.
... 4. Complex is better than complicated.
... '''.splitlines(keepends=True)
>>> len(text1)
4
>>> text1[0][-1]
'\n'
>>> text2 = ''' 1. Beautiful is better than ugly.
... 3. Simple is better than complex.
... 4. Complicated is better than complex.
... 5. Flat is better than nested.
... '''.splitlines(keepends=True)
接下来我们实例化一个 Differ 对象:
>>> d = Differ()
请注意在实例化 Differ
对象时我们可以传入函数来过滤掉“垃圾”行和字符。
最后,我们比较两个序列:
>>> result = list(d.compare(text1, text2))
result
是一个字符串列表,让我们将其美化打印出来:
>>> from pprint import pprint
>>> pprint(result)
[' 1. Beautiful is better than ugly.\n',
'- 2. Explicit is better than implicit.\n',
'- 3. Simple is better than complex.\n',
'+ 3. Simple is better than complex.\n',
'? ++\n',
'- 4. Complex is better than complicated.\n',
'? ^ ---- ^\n',
'+ 4. Complicated is better than complex.\n',
'? ++++ ^ ^\n',
'+ 5. Flat is better than nested.\n']
作为单独的多行字符串显示出来则是这样:
>>> import sys
>>> sys.stdout.writelines(result)
1. Beautiful is better than ugly.
- 2. Explicit is better than implicit.
- 3. Simple is better than complex.
+ 3. Simple is better than complex.
? ++
- 4. Complex is better than complicated.
? ^ ---- ^
+ 4. Complicated is better than complex.
? ++++ ^ ^
+ 5. Flat is better than nested.
difflib 的命令行接口
这个实例演示了如何使用 difflib 来创建一个类似于 diff
的工具。 它同样包含在 Python 源码发布包中,文件名为 Tools/scripts/diff.py
。
#!/usr/bin/env python3
""" Command line interface to difflib.py providing diffs in four formats:
* ndiff: lists every line and highlights interline changes.
* context: highlights clusters of changes in a before/after format.
* unified: highlights clusters of changes in an inline format.
* html: generates side by side comparison with change highlights.
"""
import sys, os, difflib, argparse
from datetime import datetime, timezone
def file_mtime(path):
t = datetime.fromtimestamp(os.stat(path).st_mtime,
timezone.utc)
return t.astimezone().isoformat()
def main():
parser = argparse.ArgumentParser()
parser.add_argument('-c', action='store_true', default=False,
help='Produce a context format diff (default)')
parser.add_argument('-u', action='store_true', default=False,
help='Produce a unified format diff')
parser.add_argument('-m', action='store_true', default=False,
help='Produce HTML side by side diff '
'(can use -c and -l in conjunction)')
parser.add_argument('-n', action='store_true', default=False,
help='Produce a ndiff format diff')
parser.add_argument('-l', '--lines', type=int, default=3,
help='Set number of context lines (default 3)')
parser.add_argument('fromfile')
parser.add_argument('tofile')
options = parser.parse_args()
n = options.lines
fromfile = options.fromfile
tofile = options.tofile
fromdate = file_mtime(fromfile)
todate = file_mtime(tofile)
with open(fromfile) as ff:
fromlines = ff.readlines()
with open(tofile) as tf:
tolines = tf.readlines()
if options.u:
diff = difflib.unified_diff(fromlines, tolines, fromfile, tofile, fromdate, todate, n=n)
elif options.n:
diff = difflib.ndiff(fromlines, tolines)
elif options.m:
diff = difflib.HtmlDiff().make_file(fromlines,tolines,fromfile,tofile,context=options.c,numlines=n)
else:
diff = difflib.context_diff(fromlines, tolines, fromfile, tofile, fromdate, todate, n=n)
sys.stdout.writelines(diff)
if __name__ == '__main__':
main()
textwrap
—- 文本自动换行与填充
源代码: Lib/textwrap.py
textwrap
模块提供了一些快捷函数,以及可以完成所有工作的类 TextWrapper
。 如果你只是要对一两个文本字符串进行自动换行或填充,快捷函数应该就够用了;否则的话,你应该使用 TextWrapper
的实例来提高效率。
textwrap.wrap
(text, width=70, **, initial_indent=’’, subsequent_indent=’’, expand_tabs=True, replace_whitespace=True, fix_sentence_endings=False, break_long_words=True, drop_whitespace=True, break_on_hyphens=True, tabsize=8, max_lines=None*)
对 text (字符串) 中的单独段落自动换行以使每行长度最多为 width 个字符。 返回由输出行组成的列表,行尾不带换行符。
与 TextWrapper
的实例属性对应的可选的关键字参数,具体文档见下。
textwrap.fill
(text, width=70, **, initial_indent=’’, subsequent_indent=’’, expand_tabs=True, replace_whitespace=True, fix_sentence_endings=False, break_long_words=True, drop_whitespace=True, break_on_hyphens=True, tabsize=8, max_lines=None*)
对 text 中的单独段落自动换行,并返回一个包含被自动换行段落的单独字符串。 fill()
是以下语句的快捷方式
"\n".join(wrap(text, ...))
特别要说明的是,fill()
接受与 wrap()
完全相同的关键字参数。
textwrap.shorten
(text, width, **, fix_sentence_endings=False, break_long_words=True, break_on_hyphens=True, placeholder=’ […]‘*)
折叠并截短给定的 text 以符合给定的 width。
首先,将折叠 text 中的空格(所有连续空格替换为单个空格)。 如果结果能适合 width 则将其返回。 否则将丢弃足够数量的末尾单词以使得剩余单词加 placeholder
能适合 width
:
>>> textwrap.shorten("Hello world!", width=12)
'Hello world!'
>>> textwrap.shorten("Hello world!", width=11)
'Hello [...]'
>>> textwrap.shorten("Hello world", width=10, placeholder="...")
'Hello...'
可选的关键字参数对应于 TextWrapper
的实际属性,具体见下文。 请注意文本在被传入 TextWrapper
的 fill()
函数之前会被折叠,因此改变 tabsize
, expand_tabs
, drop_whitespace
和 replace_whitespace
的值将没有任何效果。
3.4 新版功能.
textwrap.dedent
(text)
移除 text 中每一行的任何相同前缀空白符。
这可以用来清除三重引号字符串行左侧空格,而仍然在源码中显示为缩进格式。
请注意制表符和空格符都被视为是空白符,但它们并不相等:以下两行 " hello"
和 "\thello"
不会被视为具有相同的前缀空白符。
只包含空白符的行会在输入时被忽略并在输出时被标准化为单个换行符。
例如:
def test():
# end first line with \ to avoid the empty line!
s = '''\
hello
world
'''
print(repr(s)) # prints ' hello\n world\n '
print(repr(dedent(s))) # prints 'hello\n world\n'
textwrap.indent
(text, prefix, predicate=None)
将 prefix 添加到 text 中选定行的开头。
通过调用 text.splitlines(True)
来对行进行拆分。
默认情况下,prefix 会被添加到所有不是只由空白符(包括任何行结束符)组成的行。
例如:
>>> s = 'hello\n\n \nworld'
>>> indent(s, ' ')
' hello\n\n \n world'
可选的 predicate 参数可用来控制哪些行要缩进。 例如,可以很容易地为空行或只有空白符的行添加 prefix:
>>> print(indent(s, '+ ', lambda line: True))
+ hello
+
+
+ world
3.3 新版功能.
wrap()
, fill()
和 shorten()
的作用方式为创建一个 TextWrapper
实例并在其上调用单个方法。 该实例不会被重用,因此对于要使用 wrap()
和/或 fill()
来处理许多文本字符串的应用来说,创建你自己的 TextWrapper
对象可能会更有效率。
文本最好在空白符位置自动换行,包括带连字符单词的连字符之后;长单词仅在必要时会被拆分,除非 TextWrapper.break_long_words
被设为假值。
class textwrap.TextWrapper
(**kwargs)
TextWrapper
构造器接受多个可选的关键字参数。 每个关键字参数对应一个实例属性,比如说
wrapper = TextWrapper(initial_indent="* ")
相当于:
wrapper = TextWrapper()
wrapper.initial_indent = "* "
你可以多次重用相同的 TextWrapper
对象,并且你也可以在使用期间通过直接向实例属性赋值来修改它的任何选项。
TextWrapper
的实例属性(以及构造器的关键字参数)如下所示:
width
(默认:
70
) 自动换行的最大行长度。 只要输入文本中没有长于width
的单个单词,TextWrapper
就能保证没有长于width
个字符的输出行。expand_tabs
(默认:
True
) 如果为真值,则 text 中所有的制表符将使用 text 的expandtabs()
方法扩展为空格符。tabsize
(默认:
8
) 如果expand_tabs
为真值,则 text 中所有的制表符将扩展为零个或多个空格,具体取决于当前列位置和给定的制表宽度。3.3 新版功能.
replace_whitespace
(default:
True
) 如果为真值,在制表符扩展之后、自动换行之前,wrap()
方法将把每个空白字符都替换为单个空格。 会被替换的空白字符如下:制表,换行,垂直制表,进纸和回车 ('\t\n\v\f\r'
)。注解
如果
expand_tabs
为假值且replace_whitespace
为真值,每个制表符将被替换为单个空格,这与制表符扩展是 不 一样的。注解
如果
replace_whitespace
为假值,在一行的中间有可能出现换行符并导致怪异的输出。 因此,文本应当(使用str.splitlines()
或类似方法)拆分为段落并分别进行自动换行。drop_whitespace
(默认:
True
) 如果为真值,每一行开头和末尾的空白字符(在包装之后、缩进之前)会被丢弃。 但是段落开头的空白字符如果后面不带任何非空白字符则不会被丢弃。 如果被丢弃的空白字符占据了一个整行,则该整行将被丢弃。initial_indent
(默认:
''
) 将被添加到被自动换行输出内容的第一行的字符串。 其长度会被计入第一行的长度。 空字符串不会被缩进。subsequent_indent
(default:
''
) 将被添加到被自动换行输出内容除第一行外的所有行的字符串。 其长度会被计入除行一行外的所有行的长度。fix_sentence_endings
(默认:
False
) 如果为真值,TextWrapper
将尝试检测句子结尾并确保句子间总是以恰好两个空格符分隔。 对于使用等宽字体的文本来说通常都需要这样。 但是,句子检测算法并不完美:它假定句子结尾是一个小写字母加字符'.'
,'!'
或'?'
中的一个,并可能带有字符'"'
或"'"
,最后以一个空格结束。 此算法的问题之一是它无法区分以下文本中的 “Dr.”[...] Dr. Frankenstein's monster [...]
和以下文本中的 “Spot.”
[...] See Spot. See Spot run [...]
fix_sentence_endings
默认为假值。由于句子检测算法依赖于
string.lowercase
来确定“小写字母”,以及约定在句点后使用两个空格来分隔处于同一行的句子,因此只适用于英语文本。break_long_words
(默认:
True
) 如果为真值,则长度超过width
的单词将被分开以保证行的长度不会超过width
。 如果为假值,超长单词不会被分开,因而某些行的长度可能会超过width
。 (超长单词将被单独作为一行,以尽量减少超出width
的情况。)break_on_hyphens
(默认:
True
) 如果为真值,将根据英语的惯例首选在空白符和复合词的连字符之后自动换行。 如果为假值,则只有空白符会被视为合适的潜在断行位置,但如果你确实不希望出现分开的单词则你必须将break_long_words
设为假值。 之前版本的默认行为总是允许分开带有连字符的单词。max_lines
(默认:
None
) 如果不为None
,则输出内容将最多包含 max_lines 行,并使 placeholder 出现在输出内容的末尾。3.4 新版功能.
placeholder
(默认:
' [...]'
) 该文本将在输出文本被截短时出现在文本末尾。3.4 新版功能.
TextWrapper
还提供了一些公有方法,类似于模块层级的便捷函数:
wrap
(text)对 text (字符串) 中的单独段落自动换行以使每行长度最多为
width
个字符。 所有自动换行选项均获取自TextWrapper
实例的实例属性。 返回由输出行组成的列表,行尾不带换行符。 如果自动换行输出结果没有任何内容,则返回空列表。fill
(text)对 text 中的单独段落自动换行并返回包含被自动换行段落的单独字符串。
unicodedata
—- Unicode 数据库
此模块提供了对 Unicode Character Database (UCD) 的访问,其中定义了所有 Unicode 字符的字符属性。 此数据库中包含的数据编译自 UCD 版本 13.0.0。
该模块使用与 Unicode 标准附件 #44 “Unicode 字符数据库” 中所定义的相同名称和符号。 它定义了以下函数:
unicodedata.lookup
(name)
按名称查找字符。如果找到具有给定名称的字符,则返回相应的字符。 如果没有找到,则 KeyError
被引发。
在 3.3 版更改: 已添加对名称别名 和命名序列 的支持。
unicodedata.name
(chr[, default])
返回分配给字符 chr 的名称作为字符串。如果没有定义名称,则返回 default ,如果没有给出,则 ValueError
被引发。
unicodedata.decimal
(chr[, default])
返回分配给字符 chr 的十进制值作为整数。 如果没有定义这样的值,则返回 default ,如果没有给出,则 ValueError
被引发。
unicodedata.digit
(chr[, default])
返回分配给字符 chr 的数字值作为整数。 如果没有定义这样的值,则返回 default ,如果没有给出,则 ValueError
被引发。
unicodedata.numeric
(chr[, default])
返回分配给字符 chr 的数值作为浮点数。 如果没有定义这样的值,则返回 default ,如果没有给出,则 ValueError
被引发。
unicodedata.category
(chr)
返回分配给字符 chr 的常规类别为字符串。
unicodedata.bidirectional
(chr)
返回分配给字符 chr 的双向类作为字符串。如果未定义此类值,则返回空字符串。
unicodedata.combining
(chr)
返回分配给字符 chr 的规范组合类作为整数。如果没有定义组合类,则返回 0
。
unicodedata.east_asian_width
(chr)
返回分配给字符 chr 的东亚宽度作为字符串。
unicodedata.mirrored
(chr)
返回分配给字符 chr 的镜像属性为整数。如果字符在双向文本中被识别为“镜像”字符,则返回 1
,否则返回 0
。
unicodedata.decomposition
(chr)
返回分配给字符 chr 的字符分解映射作为字符串。如果未定义此类映射,则返回空字符串。
unicodedata.normalize
(form, unistr)
返回 Unicode 字符串 unistr 的正常形式 form 。 form 的有效值为 ‘NFC’ 、 ‘NFKC’ 、 ‘NFD’ 和 ‘NFKD’ 。
Unicode 标准基于规范等价和兼容性等效的定义定义了 Unicode 字符串的各种规范化形式。在 Unicode 中,可以以各种方式表示多个字符。 例如,字符 U+00C7 (带有 CEDILLA 的 LATIN CAPITAL LETTER C )也可以表示为序列 U+0043( LATIN CAPITAL LETTER C )U+0327( COMBINING CEDILLA )。
对于每个字符,有两种正规形式:正规形式 C 和正规形式 D 。正规形式D(NFD)也称为规范分解,并将每个字符转换为其分解形式。 正规形式C(NFC)首先应用规范分解,然后再次组合预组合字符。
除了这两种形式之外,还有两种基于兼容性等效的其他常规形式。 在 Unicode 中,支持某些字符,这些字符通常与其他字符统一。 例如, U+2160(ROMAN NUMERAL ONE)与 U+0049(LATIN CAPITAL LETTER I)完全相同。 但是, Unicode 支持它与现有字符集(例如 gb2312 )的兼容性。
正规形式KD(NFKD)将应用兼容性分解,即用其等价项替换所有兼容性字符。 正规形式KC(NFKC)首先应用兼容性分解,然后是规范组合。
即使两个 unicode 字符串被规范化并且人类读者看起来相同,如果一个具有组合字符而另一个没有,则它们可能无法相等。
unicodedata.is_normalized
(form, unistr)
判断 Unicode 字符串 unistr 是否为正规形式 form*。 *form 的有效值为 ‘NFC’, ‘NFKC’, ‘NFD’ 和 ‘NFKD’。
3.8 新版功能.
此外,该模块暴露了以下常量:
unicodedata.unidata_version
此模块中使用的 Unicode 数据库的版本。
unicodedata.ucd_3_2_0
这是一个与整个模块具有相同方法的对象,但对于需要此特定版本的 Unicode 数据库(如 IDNA )的应用程序,则使用 Unicode 数据库版本 3.2 。
示例:
>>> import unicodedata
>>> unicodedata.lookup('LEFT CURLY BRACKET')
'{'
>>> unicodedata.name('/')
'SOLIDUS'
>>> unicodedata.decimal('9')
9
>>> unicodedata.decimal('a')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: not a decimal
>>> unicodedata.category('A') # 'L'etter, 'u'ppercase
'Lu'
>>> unicodedata.bidirectional('\u0660') # 'A'rabic, 'N'umber
'AN'
stringprep
—- 因特网字符串预备
源代码: Lib/stringprep.py
在标识因特网上的事物(例如主机名),经常需要比较这些标识是否(相等)。 这种比较的具体执行可能会取决于应用域的不同,例如是否要区分大小写等等。 有时也可能需要限制允许的标识为仅由“可打印”字符组成。
RFC 3454 定义了在因特网协议中 Unicode 字符串的“预备”过程。 在将字符串连线传输之前,它们会先使用预备过程进行处理,之后它们将具有特定的标准形式。 该 RFC 定义了一系列表格,它们可以被组合为选项配置。 每个配置必须定义所使用的表格,stringprep
过程的其他可选项也是配置的组成部分。 stringprep
配置的一个例子是 nameprep
,它被用于国际化域名。
模块 stringprep
仅公开了来自 RFC 3454 的表格。 由于这些如果表格如果表示为字典或列表将会非常庞大,该模块在内部使用 Unicode 字符数据库。 该模块本身的源代码是使用 mkstringprep.py
工具生成的。
因此,这些表格以函数而非数据结构的形式公开。 在 RFC 中有两种表格:集合与映射。 对于集合,stringprep
提供了“特征函数”,即如果形参是集合的一部分则返回值为 True
的函数。 对于映射,它提供了映射函数:它会根据给定的键返回所关联的值。 以下是模块中所有可用函数的列表。
stringprep.in_table_a1
(code)
确定 code 是否属于 tableA.1 (Unicode 3.2 中的未分配码位)。
stringprep.in_table_b1
(code)
确定 code 是否属于 tableB.1 (通常映射为空值)。
stringprep.map_table_b2
(code)
返回 code 依据 tableB.2 (配合 NFKC 使用的大小写转换映射) 所映射的值。
stringprep.map_table_b3
(code)
返回 code 依据 tableB.3 (不附带正规化的大小写折叠映射) 所映射的值。
stringprep.in_table_c11
(code)
确定 code 是否属于 tableC.1.1 (ASCII 空白字符)。
stringprep.in_table_c12
(code)
确定 code 是否属于 tableC.1.2 (非 ASCII 空白字符)。
stringprep.in_table_c11_c12
(code)
确定 code 是否属于 tableC.1 (空白字符,C.1.1 和 C.1.2 的并集)。
stringprep.in_table_c21
(code)
确定 code 是否属于 tableC.2.1 (ASCII 控制字符)。
stringprep.in_table_c22
(code)
确定 code 是否属于 tableC.2.2 (非 ASCII 控制字符)。
stringprep.in_table_c21_c22
(code)
确定 code 是否属于 tableC.2 (控制字符,C.2.1 和 C.2.2 的并集)。
stringprep.in_table_c3
(code)
确定 code 是否属于 tableC.3 (私有使用)。
stringprep.in_table_c4
(code)
确定 code 是否属于 tableC.4 (非字符码位)。
stringprep.in_table_c5
(code)
确定 code 是否属于 tableC.5 (替代码)。
stringprep.in_table_c6
(code)
确定 code 是否属于 tableC.6 (不适用于纯文本)。
stringprep.in_table_c7
(code)
确定 code 是否属于 tableC.7 (不适用于规范表示)。
stringprep.in_table_c8
(code)
确定 code 是否属于 tableC.8 (改变显示属性或已弃用)。
stringprep.in_table_c9
(code)
确定 code 是否属于 tableC.9 (标记字符)。
stringprep.in_table_d1
(code)
确定 code 是否属于 tableD.1 (带有双向属性 “R” 或 “AL” 的字符)。
stringprep.in_table_d2
(code)
确定 code 是否属于 tableD.2 (带有双向属性 “L” 的字符)。
readline
—- GNU readline 接口
readline
模块定义了许多方便从 Python 解释器完成和读取/写入历史文件的函数。 此模块可以直接使用,或通过支持在交互提示符下完成 Python 标识符的 rlcompleter
模块使用。 使用此模块进行的设置会同时影响解释器的交互提示符以及内置 input()
函数提供的提示符。
Readline keybindings may be configured via an initialization file, typically .inputrc
in your home directory. See Readline Init File in the GNU Readline manual for information about the format and allowable constructs of that file, and the capabilities of the Readline library in general.
注解
底层的 Readline 库 API 可能使用 libedit
库来实现而不是 GNU readline。 在 macOS 上 readline
模块会在运行时检测所使用的是哪个库。
libedit
所用的配置文件与 GNU readline 的不同。 如果你要在程序中载入配置字符串你可以在 readline.__doc__
中检测文本 “libedit” 来区分 GNU readline 和 libedit。
如果你是在 macOS 上使用 editline/libedit
readline 模拟,则位于你的主目录中的初始化文件名称为 .editrc
。 例如,~/.editrc
中的以下内容将开启 vi 按键绑定以及 TAB 补全:
python:bind -vpython:bind ^I rl_complete
初始化文件
下列函数与初始化文件和用户配置有关:
readline.parse_and_bind
(string)
执行在 string 参数中提供的初始化行。 此函数会调用底层库中的 rl_parse_and_bind()
。
readline.read_init_file
([filename])
执行一个 readline 初始化文件。 默认文件名为最近所使用的文件名。 此函数会调用底层库中的 rl_read_init_file()
。
行缓冲区
下列函数会在行缓冲区上操作。
readline.get_line_buffer
()
返回行缓冲区的当前内容 (底层库中的 rl_line_buffer
)。
readline.insert_text
(string)
将文本插入行缓冲区的当前游标位置。 该函数会调用底层库中的 rl_insert_text()
,但会忽略其返回值。
readline.redisplay
()
改变屏幕的显示以反映行缓冲区的当前内容。 该函数会调用底层库中的 rl_redisplay()
。
历史文件
下列函数会在历史文件上操作:
readline.read_history_file
([filename])
载入一个 readline 历史文件,并将其添加到历史列表。 默认文件名为 ~/.history
。 此函数会调用底层库中的 read_history()
。
readline.write_history_file
([filename])
将历史列表保存为 readline 历史文件,覆盖任何现有文件。 默认文件名为 ~/.history
。 此函数会调用底层库中的 write_history()
。
readline.append_history_file
(nelements[, filename])
将历史列表的最后 nelements 项添加到历史文件。 默认文件名为 ~/.history
。 文件必须已存在。 此函数会调用底层库中的 append_history()
。 此函数仅当 Python 编译包带有支持此功能的库版本时才会存在。
3.5 新版功能.
readline.get_history_length
()
readline.set_history_length
(length)
设置或返回需要保存到历史文件的行数。 write_history_file()
函数会通过调用底层库中的 history_truncate_file()
以使用该值来截取历史文件。 负值意味着不限制历史文件的大小。
历史列表
以下函数会在全局历史列表上操作:
readline.clear_history
()
清除当前历史。 此函数会调用底层库的 clear_history()
。 此 Python 函数仅当 Python 编译包带有支持此功能的库版本时才会存在。
readline.get_current_history_length
()
返回历史列表的当前项数。 (此函数不同于 get_history_length()
,后者是返回将被写入历史文件的最大行数。)
readline.get_history_item
(index)
返回序号为 index 的历史条目的当前内容。 条目序号从一开始。 此函数会调用底层库中的 history_get()
。
readline.remove_history_item
(pos)
从历史列表中移除指定位置上的历史条目。 条目位置从零开始。 此函数会调用底层库中的 remove_history()
。
readline.replace_history_item
(pos, line)
将指定位置上的历史条目替换为 line。 条目位置从零开始。 此函数会调用底层库中的 replace_history_entry()
。
readline.add_history
(line)
将 line 添加到历史缓冲区,相当于是最近输入的一行。 此函数会调用底层库中的 add_history()
。
readline.set_auto_history
(enabled)
启用或禁用当通过 readline 读取输入时自动调用 add_history()
。 enabled 参数应为一个布尔值,当其为真值时启用自动历史,当其为假值时禁用自动历史。
3.6 新版功能.
CPython implementation detail: Auto history is enabled by default, and changes to this do not persist across multiple sessions.
启动钩子
readline.set_startup_hook
([function])
设置或移除底层库的 rl_startup_hook
回调所发起调用的函数。 如果指定了 function,它将被用作新的钩子函数;如果省略或为 None
,任何已安装的函数将被移除。 钩子函数将在 readline 打印第一个提示信息之前不带参数地被调用。
readline.set_pre_input_hook
([function])
设置或移除底层库的 rl_pre_input_hook
回调所发起调用的函数。 如果指定了 function,它将被用作新的钩子函数;如果省略或为 None
,任何已安装的函数将被移除。 钩子函数将在打印第一个提示信息之后、readline 开始读取输入字符之前不带参数地被调用。 此函数仅当 Python 编译包带有支持此功能的库版本时才会存在。
Completion
以下函数与自定义单词补全函数的实现有关。 这通常使用 Tab 键进行操作,能够提示并自动补全正在输入的单词。 默认情况下,Readline 设置为由 rlcompleter
来补全交互模式解释器的 Python 标识符。 如果 readline
模块要配合自定义的补全函数来使用,则需要设置不同的单词分隔符。
readline.set_completer
([function])
设置或移除补全函数。 如果指定了 function*,它将被用作新的补全函数;如果省略或为 None
,任何已安装的补全函数将被移除。 补全函数的调用形式为 function(text, state)
,其中 *state 为 0
, 1
, 2
, …, 直至其返回一个非字符串值。 它应当返回下一个以 text 开头的候选补全内容。
已安装的补全函数将由传递给底层库中 rl_completion_matches()
的 entry_func 回调函数来发起调用。 text 字符串来自于底层库中 rl_attempted_completion_function
回调函数的第一个形参。
readline.get_completer
()
获取补全函数,如果没有设置补全函数则返回 None
。
readline.get_completion_type
()
获取正在尝试的补全类型。 此函数会将底层库中的 rl_completion_type
变量作为一个整数返回。
readline.get_begidx
()
readline.get_endidx
()
获取完全范围的开始和结束索引号。 这些索引号就是传递给下层库的 rl_attempted_completion_function
回调的 start 和 end 参数。 具体值在同一个输入编辑场景中可能不同,具体取决于下层的 C readline 实现。 例如:已知 libedit 的行为就不同于 libreadline。
readline.set_completer_delims
(string)
readline.get_completer_delims
()
设置或获取补全的单词分隔符。 此分隔符确定了要考虑补全的单词的开始和结束位置(补全域)。 这些函数会访问底层库的 rl_completer_word_break_characters
变量。
readline.set_completion_display_matches_hook
([function])
设置或移除补全显示函数。 如果指定了 function,它将被用作新的补全显示函数;如果省略或为 None
,任何已安装的补全显示函数将被移除。 此函数会设置或清除底层库的 rl_completion_display_matches_hook
回调函数。 补全显示函数会在每次需要显示匹配项时以 function(substitution, [matches], longest_match_length)
的形式被调用。
示例
以下示例演示了如何使用 readline
模块的历史读取或写入函数来自动加载和保存用户主目录下名为 .python_history
的历史文件。 以下代码通常应当在交互会话期间从用户的 PYTHONSTARTUP
文件自动执行。
import atexit
import os
import readline
histfile = os.path.join(os.path.expanduser("~"), ".python_history")
try:
readline.read_history_file(histfile)
# default history len is -1 (infinite), which may grow unruly
readline.set_history_length(1000)
except FileNotFoundError:
pass
atexit.register(readline.write_history_file, histfile)
此代码实际上会在 Python 运行于 交互模式 时自动运行。
以下示例实现了同样的目标,但是通过只添加新历史的方式来支持并发的交互会话。
import atexit
import os
import readline
histfile = os.path.join(os.path.expanduser("~"), ".python_history")
try:
readline.read_history_file(histfile)
h_len = readline.get_current_history_length()
except FileNotFoundError:
open(histfile, 'wb').close()
h_len = 0
def save(prev_h_len, histfile):
new_h_len = readline.get_current_history_length()
readline.set_history_length(1000)
readline.append_history_file(new_h_len - prev_h_len, histfile)
atexit.register(save, h_len, histfile)
以下示例扩展了 code.InteractiveConsole
类以支持历史保存/恢复。
import atexit
import code
import os
import readline
class HistoryConsole(code.InteractiveConsole):
def __init__(self, locals=None, filename="<console>",
histfile=os.path.expanduser("~/.console-history")):
code.InteractiveConsole.__init__(self, locals, filename)
self.init_history(histfile)
def init_history(self, histfile):
readline.parse_and_bind("tab: complete")
if hasattr(readline, "read_history_file"):
try:
readline.read_history_file(histfile)
except FileNotFoundError:
pass
atexit.register(self.save_history, histfile)
def save_history(self, histfile):
readline.set_history_length(1000)
readline.write_history_file(histfile)
rlcompleter
—- GNU readline 的补全函数
源代码: Lib/rlcompleter.py
rlcompeleter
通过补全有效的 Python 标识符和关键字定义了一个适用于 readline
模块的补全函数。
当此模块在具有可用的 readline
模块的 Unix 平台被导入, 一个 Completer
实例将被自动创建并且它的 complete()
方法将设置为 readline
的补全器.
示例:
>>> import rlcompleter
>>> import readline
>>> readline.parse_and_bind("tab: complete")
>>> readline. <TAB PRESSED>
readline.__doc__ readline.get_line_buffer( readline.read_init_file(
readline.__file__ readline.insert_text( readline.set_completer(
readline.__name__ readline.parse_and_bind(
>>> readline.
rlcompleter
模块是为了使用 Python 的 交互模式 而设计的。 除非 Python 是通过 -S
选项运行, 这个模块总是自动地被导入且配置 。
在没有 readline
的平台, 此模块定义的 Completer
类仍然可以用于自定义行为.
Completer 对象
Completer 对象具有以下方法:
Completer.complete
(text, state)
为 text 返回第 state 项补全。
如果指定的 text 不包含句点字符 ('.'
),它将根据当前 __main__
, builtins
和保留关键字(定义于 keyword
模块)所定义的名称进行补全。
如果为带有句点的名称执行调用,它将尝试尽量求值直到最后一部分为止而不产生附带影响(函数不会被求值,但它可以生成对 __getattr__()
的调用),并通过 dir()
函数来匹配剩余部分。 在对表达式求值期间引发的任何异常都会被捕获、静默处理并返回 None
。
二进制数据服务
下面描述的一些库 文本处理服务 也可以使用 ASCII 兼容的二进制格式(例如 re
)或所有二进制数据(例如 difflib
)。
struct
—- 将字节串解读为打包的二进制数据- 函数和异常
- 格式字符串
- 字节顺序,大小和对齐方式
- 格式字符
- 例子
- 类
codecs
—- 编解码器注册和相关基类- 编解码器基类
- 错误处理方案
- 无状态的编码和解码
- 增量式的编码和解码
- IncrementalEncoder 对象
- IncrementalDecoder 对象
- 流式的编码和解码
- StreamWriter 对象
- StreamReader 对象
- StreamReaderWriter 对象
- StreamRecoder 对象
- 编码格式与 Unicode
- 标准编码
- Python 专属的编码格式
- 文字编码
- 二进制转换
- 文字转换
encodings.idna
—- 应用程序中的国际化域名encodings.mbcs
—- Windows ANSI代码页encodings.utf_8_sig
—- 带BOM签名的UTF-8编解码器
- 编解码器基类
struct
—- 将字节串解读为打包的二进制数据
源代码: Lib/struct.py
此模块可以执行 Python 值和以 Python bytes
对象表示的 C 结构之间的转换。 这可以被用来处理存储在文件中或是从网络连接等其他来源获取的二进制数据。 它使用 格式字符串 作为 C 结构布局的精简描述以及与 Python 值的双向转换。
注解
默认情况下,打包给定 C 结构的结果会包含填充字节以使得所涉及的 C 类型保持正确的对齐;类似地,对齐在解包时也会被纳入考虑。 选择此种行为的目的是使得被打包结构的字节能与相应 C 结构在内存中的布局完全一致。 要处理平台独立的数据格式或省略隐式的填充字节,请使用 standard
大小和对齐而不是 native
大小和对齐。
某些 struct
的函数(以及 Struct
的方法)接受一个 buffer 参数。 这将指向实现了 缓冲协议 并提供只读或是可读写缓冲的对象。 用于此目的的最常见类型为 bytes
和 bytearray
,但许多其他可被视为字节数组的类型也实现了缓冲协议,因此它们无需额外从 bytes
对象复制即可被读取或填充。
函数和异常
此模块定义了下列异常和函数:
exception struct.error
会在多种场合下被引发的异常;其参数为一个描述错误信息的字符串。
struct.pack
(format, v1, v2, …)
返回一个 bytes 对象,其中包含根据格式字符串 format 打包的值 v1, v2, … 参数个数必须与格式字符串所要求的值完全匹配。
struct.pack_into
(format, buffer, offset, v1, v2, …)
根据格式字符串 format 打包 v1, v2, … 等值并将打包的字节串写入可写缓冲区 buffer 从 offset 开始的位置。 请注意 offset 是必需的参数。
struct.unpack
(format, buffer)
根据格式字符串 format 从缓冲区 buffer 解包(假定是由 pack(format, ...)
打包)。 结果为一个元组,即使其只包含一个条目。 缓冲区的字节大小必须匹配格式所要求的大小,如 calcsize()
所示。
struct.unpack_from
(format, /, buffer, offset=0)
对 buffer 从位置 offset 开始根据格式字符串 format 进行解包。 结果为一个元组,即使其中只包含一个条目。 缓冲区的字节大小从位置 offset 开始必须至少为 calcsize()
显示的格式所要求的大小。
struct.iter_unpack
(format, buffer)
根据格式字符串 format 以迭代方式从缓冲区 buffer 解包。 此函数返回一个迭代器,它将从缓冲区读取相同大小的块直至其内容全部耗尽。 缓冲区的字节大小必须整数倍于格式所要求的大小,如 calcsize()
所示。
每次迭代将产生一个如格式字符串所指定的元组。
3.4 新版功能.
struct.calcsize
(format)
返回与格式字符串 format 相对应的结构的大小(亦即 pack(format, ...)
所产生的字节串对象的大小)。
格式字符串
格式字符串是用来在打包和解包数据时指定预期布局的机制。 它们使用指定被打包/解包数据类型的 格式字符 进行构建。 此外,还有一些特殊字符用来控制 字节顺序,大小和对齐方式。
字节顺序,大小和对齐方式
默认情况下,C类型以机器的本机格式和字节顺序表示,并在必要时通过跳过填充字节进行正确对齐(根据C编译器使用的规则)。
或者,根据下表,格式字符串的第一个字符可用于指示打包数据的字节顺序,大小和对齐方式:
字符 | 字节顺序 | 大小 | 对齐方式 |
---|---|---|---|
@ |
按原字节 | 按原字节 | 按原字节 |
= |
按原字节 | 标准 | 无 |
< |
小端 | 标准 | 无 |
> |
大端 | 标准 | 无 |
! |
网络(=大端) | 标准 | 无 |
如果第一个字符不是其中之一,则假定为 '@'
。
本机字节顺序可能为大端或是小端,取决于主机系统的不同。 例如, Intel x86 和 AMD64 (x86-64) 是小端的;Motorola 68000 和 PowerPC G5 是大端的;ARM 和 Intel Itanium 具有可切换的字节顺序(双端)。 请使用 sys.byteorder
来检查你的系统字节顺序。
本机大小和对齐方式是使用 C 编译器的 sizeof
表达式来确定的。 这总是会与本机字节顺序相绑定。
标准大小仅取决于格式字符。
请注意 '@'
和 '='
之间的区别:两个都使用本机字节顺序,但后者的大小和对齐方式是标准化的。
形式 '!'
代表网络字节顺序总是使用在 IETF RFC 1700 中所定义的大端序。
没有什么方式能指定非本机字节顺序(强制字节对调);请正确选择使用 '<'
或 '>'
。
注释:
- 填充只会在连续结构成员之间自动添加。 填充不会添加到已编码结构的开头和末尾。
- 当使用非本机大小和对齐方式即 ‘<’, ‘>’, ‘=’, and ‘!’ 时不会添加任何填充。
- 要将结构的末尾对齐到符合特定类型的对齐要求,请以该类型代码加重复计数的零作为格式结束。
格式字符
格式字符具有以下含义;C 和 Python 值之间的按其指定类型的转换应当是相当明显的。 ‘标准大小’列是指当使用标准大小时以字节表示的已打包值大小;也就是当格式字符串以 '<'
, '>'
, '!'
或 '='
之一开头的情况。 当使用本机大小时,已打包值的大小取决于具体的平台。
格式 | C 类型 | Python 类型 | 标准大小 | 备注 |
---|---|---|---|---|
x |
填充字节 | 无 | ||
c |
char | 长度为 1 的字节串 | 1 | |
b |
signed char | 整数 | 1 | (1), (2) |
B |
unsigned char | 整数 | 1 | (2) |
? |
_Bool | bool | 1 | (1) |
h |
short | 整数 | 2 | (2) |
H |
unsigned short | 整数 | 2 | (2) |
i |
int | 整数 | 4 | (2) |
I |
unsigned int | 整数 | 4 | (2) |
l |
long | 整数 | 4 | (2) |
L |
unsigned long | 整数 | 4 | (2) |
q |
long long | 整数 | 8 | (2) |
Q |
unsigned long long | 整数 | 8 | (2) |
n |
ssize_t |
整数 | (3) | |
N |
size_t |
整数 | (3) | |
e |
(6) | float | 2 | (4) |
f |
float | float | 4 | (4) |
d |
double | float | 8 | (4) |
s |
char[] | 字节串 | ||
p |
char[] | 字节串 | ||
P |
void* | 整数 | (5) |
在 3.3 版更改: 增加了对 'n'
和 'N'
格式的支持
在 3.6 版更改: 添加了对 'e'
格式的支持。
注释:
'?'
转换码对应于 C99 定义的 _Bool 类型。 如果此类型不可用,则使用 char 来模拟。 在标准模式下,它总是以一个字节表示。当尝试使用任何整数转换码打包一个非整数时,如果该非整数具有
__index__()
方法,则会在打包之前调用该方法将参数转换为一个整数。在 3.2 版更改: 增加了针对非整数使用
__index__()
方法的特性。'n'
和'N'
转换码仅对本机大小可用(选择为默认或使用'@'
字节顺序字符)。 对于标准大小,你可以使用适合你的应用的任何其他整数格式。对于
'f'
,'d'
和'e'
转换码,打包表示形式将使用 IEEE 754 binary32, binary64 或 binary16 格式 (分别对应于'f'
,'d'
或'e'
),无论平台使用何种浮点格式。'P'
格式字符仅对本机字节顺序可用(选择为默认或使用'@'
字节顺序字符)。 字节顺序字符'='
选择使用基于主机系统的小端或大端排序。 struct 模块不会将其解读为本机排序,因此'P'
格式将不可用。IEEE 754 binary16 “半精度” 类型是在 IEEE 754 标准 的 2008 修订版中引入的。 它包含一个符号位,5 个指数位和 11 个精度位(明确存储 10 位),可以完全精确地表示大致范围在
6.1e-05
和6.5e+04
之间的数字。 此类型并不被 C 编译器广泛支持:在一台典型的机器上,可以使用 unsigned short 进行存储,但不会被用于数学运算。 请参阅维基百科页面 half-precision floating-point format 了解详情。
格式字符之前可以带有整数重复计数。 例如,格式字符串 '4h'
的含义与 'hhhh'
完全相同。
格式之间的空白字符会被忽略;但是计数及其格式字符中不可有空白字符。
对于 's'
格式字符,计数会被解析为字节的长度,而不是像其他格式字符那样的重复计数;例如,'10s'
表示一个 10 字节的字节串,而 '10c'
表示 10 个字符。 如果未给出计数,则默认值为 1。 对于打包操作,字节串会被适当地截断或填充空字节以符合要求。 对于解包操作,结果字节对象总是恰好具有指定数量的字节。 作为特殊情况,'0s'
表示一个空字符串(而 '0c'
表示 0 个字符)。
当使用某一种整数格式 ('b'
, 'B'
, 'h'
, 'H'
, 'i'
, 'I'
, 'l'
, 'L'
, 'q'
, 'Q'
) 打包值 x
时,如果 x
在该格式的有效范围之外则将引发 struct.error
。
在 3.1 版更改: 在之前版本中,某些整数格式包装了超范围的值并会引发 DeprecationWarning
而不是 struct.error
。
'p'
格式字符用于编码“Pascal 字符串”,即存储在由计数指定的 固定长度字节 中的可变长度短字符串。 所存储的第一个字节为字符串长度或 255 中的较小值。 之后是字符串对应的字节。 如果传入 pack()
的字符串过长(超过计数值减 1),则只有字符串前 count-1
个字节会被存储。 如果字符串短于 count-1
,则会填充空字节以使得恰好使用了 count 个字节。 请注意对于 unpack()
,'p'
格式字符会消耗 count
个字节,但返回的字符串永远不会包含超过 255 个字节。
对于 '?'
格式字符,返回值为 True
或 False
。 在打包时将会使用参数对象的逻辑值。 以本机或标准 bool 类型表示的 0 或 1 将被打包,任何非零值在解包时将为 True
。
例子
注解
所有示例都假定使用一台大端机器的本机字节顺序、大小和对齐方式。
打包/解包三个整数的基础示例:
>>> from struct import *
>>> pack('hhl', 1, 2, 3)
b'\x00\x01\x00\x02\x00\x00\x00\x03'
>>> unpack('hhl', b'\x00\x01\x00\x02\x00\x00\x00\x03')
(1, 2, 3)
>>> calcsize('hhl')
8
解包的字段可通过将它们赋值给变量或将结果包装为一个具名元组来命名:
>>> record = b'raymond \x32\x12\x08\x01\x08'
>>> name, serialnum, school, gradelevel = unpack('<10sHHb', record)
>>> from collections import namedtuple
>>> Student = namedtuple('Student', 'name serialnum school gradelevel')
>>> Student._make(unpack('<10sHHb', record))
Student(name=b'raymond ', serialnum=4658, school=264, gradelevel=8)
格式字符的顺序可能对大小产生影响,因为满足对齐要求所需的填充是不同的:
>>> pack('ci', b'*', 0x12131415)
b'*\x00\x00\x00\x12\x13\x14\x15'
>>> pack('ic', 0x12131415, b'*')
b'\x12\x13\x14\x15*'
>>> calcsize('ci')
8
>>> calcsize('ic')
5
以下格式 'llh0l'
指定在末尾有两个填充字节,假定 long 类型按 4 个字节的边界对齐:
>>> pack('llh0l', 1, 2, 3)
b'\x00\x00\x00\x01\x00\x00\x00\x02\x00\x03\x00\x00'
这仅当本机大小和对齐方式生效时才会起作用;标准大小和对齐方式并不会强制进行任何对齐。
类
struct
模块还定义了以下类型:
class struct.Struct
(format)
返回一个新的 Struct 对象,它会根据格式字符串 format 来写入和读取二进制数据。 一次性地创建 Struct 对象并调用其方法相比使用同样的格式调用 struct
函数更为高效,因为这样格式字符串只需被编译一次。
注解
传递给 Struct
和模块层级函数的已编译版最新格式字符串会被缓存,因此只使用少量格式字符串的程序无需担心重用单独的 Struct
实例。
已编译的 Struct 对象支持以下方法和属性:
pack
(v1, v2, …)等价于
pack()
函数,使用了已编译的格式。 (len(result)
将等于size
。)pack_into
(buffer, offset, v1, v2, …)等价于
pack_into()
函数,使用了已编译的格式。unpack
(buffer)等价于
unpack()
函数,使用了已编译的格式。 缓冲区的字节大小必须等于size
。unpack_from
(buffer, offset=0)等价于
unpack_from()
函数,使用了已编译的格式。 缓冲区的字节大小从位置 offset 开始必须至少为size
。iter_unpack
(buffer)等价于
iter_unpack()
函数,使用了已编译的格式。 缓冲区的大小必须为size
的整数倍。3.4 新版功能.
format
用于构造此 Struct 对象的格式字符串。
在 3.7 版更改: 格式字符串类型现在是
str
而不再是bytes
。size
计算出对应于
format
的结构大小(亦即pack()
方法所产生的字节串对象的大小)。
codecs
—- 编解码器注册和相关基类
源代码: Lib/codecs.py
这个模块定义了标准 Python 编解码器(编码器和解码器)的基类,并提供接口用来访问内部的 Python 编解码器注册表,该注册表负责管理编解码器和错误处理的查找过程。 大多数标准编解码器都属于 文本编码,它们可将文本编码为字节串,但也提供了一些编解码器可将文本编码为文本,以及字节串编码为字节串。 自定义编解码器可以在任意类型间进行编码和解码,但某些模块特性仅适用于 文本编码 或将数据编码为 字节串
的编解码器。
该模块定义了以下用于使用任何编解码器进行编码和解码的函数:
codecs.encode
(obj, encoding=’utf-8’, errors=’strict’)
使用为 encoding 注册的编解码器对 obj 进行编码。
可以给定 Errors 以设置所需要的错误处理方案。 默认的错误处理方案 'strict'
表示编码错误将引发 ValueError
(或更特定编解码器相关的子类,例如 UnicodeEncodeError
)。
codecs.decode
(obj, encoding=’utf-8’, errors=’strict’)
使用为 encoding 注册的编解码器对 obj 进行解码。
可以给定 Errors 以设置所需要的错误处理方案。 默认的错误处理方案 'strict'
表示编码错误将引发 ValueError
(或更特定编解码器相关的子类,例如 UnicodeDecodeError
)。
每种编解码器的完整细节也可以直接查找获取:
codecs.lookup
(encoding)
在 Python 编解码器注册表中查找编解码器信息,并返回一个 CodecInfo
对象,其定义见下文。
首先将会在注册表缓存中查找编码,如果未找到,则会扫描注册的搜索函数列表。 如果没有找到 CodecInfo
对象,则将引发 LookupError
。 否则,CodecInfo
对象将被存入缓存并返回给调用者。
class codecs.CodecInfo
(encode, decode, streamreader=None, streamwriter=None, incrementalencoder=None, incrementaldecoder=None, name=None)
查找编解码器注册表所得到的编解码器细节信息。 构造器参数将保存为同名的属性:
name
编码名称
encode
decode
无状态的编码和解码函数。 它们必须是具有与 Codec 的
encode()
和decode()
方法相同接口的函数或方法。 这些函数或方法应当工作于无状态的模式。incrementalencoder
incrementaldecoder
增量式的编码器和解码器类或工厂函数。 这些函数必须分别提供由基类
IncrementalEncoder
和IncrementalDecoder
所定义的接口。 增量式编解码器可以保持状态。streamwriter
streamreader
流式写入器和读取器类或工厂函数。 这些函数必须分别提供由基类
StreamWriter
和StreamReader
所定义的接口。 流式编解码器可以保持状态。
为了简化对各种编解码器组件的访问,本模块提供了以下附加函数,它们使用 lookup()
来执行编解码器查找:
codecs.getencoder
(encoding)
查找给定编码的编解码器并返回其编码器函数。
在编码无法找到时将引发 LookupError
。
codecs.getdecoder
(encoding)
查找给定编码的编解码器并返回其解码器函数。
在编码无法找到时将引发 LookupError
。
codecs.getincrementalencoder
(encoding)
查找给定编码的编解码器并返回其增量式编码器类或工厂函数。
在编码无法找到或编解码器不支持增量式编码器时将引发 LookupError
。
codecs.getincrementaldecoder
(encoding)
查找给定编码的编解码器并返回其增量式解码器类或工厂函数。
在编码无法找到或编解码器不支持增量式解码器时将引发 LookupError
。
codecs.getreader
(encoding)
查找给定编码的编解码器并返回其 StreamReader
类或工厂函数。
在编码无法找到时将引发 LookupError
。
codecs.getwriter
(encoding)
查找给定编码的编解码器并返回其 StreamWriter
类或工厂函数。
在编码无法找到时将引发 LookupError
。
自定义编解码器的启用是通过注册适当的编解码器搜索函数:
codecs.register
(search_function)
注册一个编解码器搜索函数。 搜索函数预期接收一个参数,即全部以小写字母表示的编码格式名称,其中中连字符和空格会被转换为下划线,并返回一个 CodecInfo
对象。 在搜索函数无法找到给定编码格式的情况下,它应当返回 None
。
在 3.9 版更改: 连字符和空格会被转换为下划线。
codecs.unregister
(search_function)
注销一个编解码器搜索函数并清空注册表缓存。 如果指定搜索函数未被注册,则不做任何操作。
3.10 新版功能.
虽然内置的 open()
和相关联的 io
模块是操作已编码文本文件的推荐方式,但本模块也提供了额外的工具函数和类,允许在操作二进制文件时使用更多各类的编解码器:
codecs.open
(filename, mode=’r’, encoding=None, errors=’strict’, buffering=- 1)
使用给定的 mode 打开已编码的文件并返回一个 StreamReaderWriter
的实例,提供透明的编码/解码。 默认的文件模式为 'r'
,表示以读取模式打开文件。
注解
下层的已编码文件总是以二进制模式打开。 在读取和写入时不会自动执行 '\n'
的转换。 mode 参数可以是内置 open()
函数所接受的任意二进制模式;'b'
会被自动添加。
encoding 指定文件所要使用的编码格式。 允许任何编码为字节串或从字节串解码的编码格式,而文件方法所支持的数据类型则取决于所使用的编解码器。
可以指定 errors 来定义错误处理方案。 默认值 'strict'
表示在出现编码错误时引发 ValueError
。
buffering 的含义与内置 open()
函数中的相同。 默认值 -1 表示将使用默认的缓冲区大小。
codecs.EncodedFile
(file, data_encoding, file_encoding=None, errors=’strict’)
返回一个 StreamRecoder
实例,它提供了 file 的透明转码包装版本。 当包装版本被关闭时原始文件也会被关闭。
写入已包装文件的数据会根据给定的 data_encoding 解码,然后以使用 file_encoding 的字节形式写入原始文件。 从原始文件读取的字节串将根据 file_encoding 解码,其结果将使用 data_encoding 进行编码。
如果 file_encoding 未给定,则默认为 data_encoding。
可以指定 errors 来定义错误处理方案。 默认值 'strict'
表示在出现编码错误时引发 ValueError
。
codecs.iterencode
(iterator, encoding, errors=’strict’, **kwargs)
使用增量式编码器通过迭代来编码由 iterator 所提供的输入。 此函数属于 generator。 errors 参数(以及任何其他关键字参数)会被传递给增量式编码器。
此函数要求编解码器接受 str
对象形式的文本进行编码。 因此它不支持字节到字节的编码器,例如 base64_codec
。
codecs.iterdecode
(iterator, encoding, errors=’strict’, **kwargs)
使用增量式解码器通过迭代来解码由 iterator 所提供的输入。 此函数属于 generator。 errors 参数(以及任何其他关键字参数)会被传递给增量式解码器。
此函数要求编解码器接受 bytes
对象进行解码。 因此它不支持文本到文本的编码器,例如 rot_13
,但是 rot_13
可以通过同样效果的 iterencode()
来使用。
本模块还提供了以下常量,适用于读取和写入依赖于平台的文件:
codecs.BOM
codecs.BOM_BE
codecs.BOM_LE
codecs.BOM_UTF8
codecs.BOM_UTF16
codecs.BOM_UTF16_BE
codecs.BOM_UTF16_LE
codecs.BOM_UTF32
codecs.BOM_UTF32_BE
codecs.BOM_UTF32_LE
这些常量定义了多种字节序列,即一些编码格式的 Unicode 字节顺序标记(BOM)。 它们在 UTF-16 和 UTF-32 数据流中被用以指明所使用的字节顺序,并在 UTF-8 中被用作 Unicode 签名。 BOM_UTF16
是 BOM_UTF16_BE
或 BOM_UTF16_LE
,具体取决于平台的本机字节顺序,BOM
是 BOM_UTF16
的别名, BOM_LE
是 BOM_UTF16_LE
的别名,BOM_BE
是 BOM_UTF16_BE
的别名。 其他序列则表示 UTF-8 和 UTF-32 编码格式中的 BOM。
编解码器基类
codecs
模块定义了一系列基类用来定义配合编解码器对象进行工作的接口,并且也可用作定制编解码器实现的基础。
每种编解码器必须定义四个接口以便用作 Python 中的编解码器:无状态编码器、无状态解码器、流读取器和流写入器。 流读取器和写入器通常会重用无状态编码器/解码器来实现文件协议。 编解码器作者还需要定义编解码器将如何处理编码和解码错误。
错误处理方案
为了简化和标准化错误处理,编解码器可以通过接受 errors 字符串参数来实现不同的错误处理方案。 所有标准的 Python 编解码器都定义并实现了以下字符串值:
值 | 含意 |
---|---|
‘strict’ |
引发 UnicodeError (或其子类);这是默认的方案。 在 strict_errors() 中实现。 |
‘ignore’ |
忽略错误格式的数据并且不加进一步通知就继续执行。 在 ignore_errors() 中实现。 |
以下错误处理方案仅适用于 文本编码:
值 | 含意 |
---|---|
‘replace’ |
使用适当的替换标记进行替换;Python 内置编解码器将在解码时使用官方 U+FFFD 替换字符,而在编码时使用 ‘?’ 。 在 replace_errors() 中实现。 |
‘xmlcharrefreplace’ |
使用适当的 XML 字符引用进行替换(仅在编码时)。 在 xmlcharrefreplace_errors() 中实现。 |
‘backslashreplace’ |
使用带反斜杠的转义序列进行替换。 在 backslashreplace_errors() 中实现。 |
‘namereplace’ |
使用 \N{…} 转义序列进行替换(仅在编码时)。 在 namereplace_errors() 中实现。 |
‘surrogateescape’ |
在解码时,将字节替换为 U+DC80 至 U+DCFF 范围内的单个代理代码。 当在编码数据时使用 ‘surrogateescape’ 错误处理方案时,此代理将被转换回相同的字节。 (请参阅 PEP 383 了解详情。) |
此外,以下错误处理方案被专门用于指定的编解码器:
值 | 编解码器 | 含意 |
---|---|---|
‘surrogatepass’ |
utf-8, utf-16, utf-32, utf-16-be, utf-16-le, utf-32-be, utf-32-le | 允许编码和解码代理代码。 这些编解码器通常会将出现的代理代码视为错误。 |
3.1 新版功能: 'surrogateescape'
和 'surrogatepass'
错误处理方案。
在 3.4 版更改: 'surrogatepass'
错误处理方案现在适用于 utf-16* 和 utf-32* 编解码器。
3.5 新版功能: 'namereplace'
错误处理方案。
在 3.5 版更改: 'backslashreplace'
错误处理方案现在适用于解码和转换。
允许的值集合可以通过注册新命名的错误处理方案来扩展:
codecs.register_error
(name, error_handler)
在名称 name 之下注册错误处理函数 error_handler*。 当 *name 被指定为错误形参时,error_handler 参数所指定的对象将在编码和解码期间发生错误的情况下被调用,
对于编码操作,将会调用 error_handler 并传入一个 UnicodeEncodeError
实例,其中包含有关错误位置的信息。 错误处理程序必须引发此异常或别的异常,或者也可以返回一个元组,其中包含输入的不可编码部分的替换对象,以及应当继续进行编码的位置。 替换对象可以为 str
或 bytes
类型。 如果替换对象为字节串,编码器将简单地将其复制到输出缓冲区。 如果替换对象为字符串,编码器将对替换对象进行编码。 对原始输入的编码操作会在指定位置继续进行。 负的位置值将被视为相对于输入字符串的末尾。 如果结果位置超出范围则将引发 IndexError
。
解码和转换的做法很相似,不同之处在于将把 UnicodeDecodeError
或 UnicodeTranslateError
传给处理程序,并且来自错误处理程序的替换对象将被直接放入输出。
之前注册的错误处理方案(包括标准错误处理方案)可通过名称进行查找:
codecs.lookup_error
(name)
返回之前在名称 name 之下注册的错误处理方案。
在处理方案无法找到时将引发 LookupError
。
以下标准错误处理方案也可通过模块层级函数的方式来使用:
codecs.strict_errors
(exception)
实现 'strict'
错误处理方案:每个编码或解码错误都会引发 UnicodeError
。
codecs.replace_errors
(exception)
实现 'replace'
错误处理方案 (仅用于 文本编码):编码错误替换为 '?'
(并由编解码器编码),解码错误替换为 '\ufffd'
(Unicode 替换字符)。
codecs.ignore_errors
(exception)
实现 'ignore'
错误处理方案:忽略错误格式的数据并且不加进一步通知就继续执行。
codecs.xmlcharrefreplace_errors
(exception)
实现 'xmlcharrefreplace'
错误处理方案 (仅用于 文本编码 的编码过程):不可编码的字符将以适当的 XML 字符引用进行替换。
codecs.backslashreplace_errors
(exception)
实现 'backslashreplace'
错误处理方案 (仅用于 文本编码):错误格式的数据将以带反斜杠的转义序列进行替换。
codecs.namereplace_errors
(exception)
实现 'namereplace'
错误处理方案 (仅用于 文本编码 的编码过程):不可编码的字符将以 \N{...}
转义序列进行替换。
3.5 新版功能.
无状态的编码和解码
基本 Codec
类定义了这些方法,同时还定义了无状态编码器和解码器的函数接口:
Codec.encode
(input[, errors])
编码 input 对象并返回一个元组 (输出对象, 消耗长度)。 例如,text encoding 会使用特定的字符集编码格式 (例如 cp1252
或 iso-8859-1
) 将字符串转换为字节串对象。
errors 参数定义了要应用的错误处理方案。 默认为 'strict'
处理方案。
此方法不一定会在 Codec
实例中保存状态。 可使用必须保存状态的 StreamWriter
作为编解码器以便高效地进行编码。
编码器必须能够处理零长度的输入并在此情况下返回输出对象类型的空对象。
Codec.decode
(input[, errors])
解码 input 对象并返回一个元组 (输出对象, 消耗长度)。 例如,text encoding 的解码操作会使用特定的字符集编码格式将字节串对象转换为字符串对象。
对于文本编码格式和字节到字节编解码器,input 必须为一个字节串对象或提供了只读缓冲区接口的对象 — 例如,缓冲区对象和映射到内存的文件。
errors 参数定义了要应用的错误处理方案。 默认为 'strict'
处理方案。
此方法不一定会在 Codec
实例中保存状态。 可使用必须保存状态的 StreamReader
作为编解码器以便高效地进行解码。
解码器必须能够处理零长度的输入并在此情况下返回输出对象类型的空对象。
增量式的编码和解码
IncrementalEncoder
和 IncrementalDecoder
类提供了增量式编码和解码的基本接口。 对输入的编码/解码不是通过对无状态编码器/解码器的一次调用,而是通过对增量式编码器/解码器的 encode()
/decode()
方法的多次调用。 增量式编码器/解码器会在方法调用期间跟踪编码/解码过程。
调用 encode()
/decode()
方法后的全部输出相当于将所有通过无状态编码器/解码器进行编码/解码的单个输入连接在一起所得到的输出。
IncrementalEncoder 对象
IncrementalEncoder
类用来对一个输入进行分步编码。 它定义了以下方法,每个增量式编码器都必须定义这些方法以便与 Python 编解码器注册表相兼容。
class codecs.IncrementalEncoder
(errors=’strict’)
IncrementalEncoder
实例的构造器。
所有增量式编码器必须提供此构造器接口。 它们可以自由地添加额外的关键字参数,但只有在这里定义的参数才会被 Python 编解码器注册表所使用。
IncrementalEncoder
可以通过提供 errors 关键字参数来实现不同的错误处理方案。
errors 参数将被赋值给一个同名的属性。 通过对此属性赋值就可以在 IncrementalEncoder
对象的生命期内在不同的错误处理策略之间进行切换。
encode
(object[, final])编码 object (会将编码器的当前状态纳入考虑) 并返回已编码的结果对象。 如果这是对
encode()
的最终调用则 final 必须为真值(默认为假值)。reset
()将编码器重置为初始状态。 输出将被丢弃:调用
.encode(object, final=True)
,在必要时传入一个空字节串或字符串,重置编码器并得到输出。getstate
()返回编码器的当前状态,该值必须为一个整数。 实现应当确保
0
是最常见的状态。 (比整数更复杂的状态表示可以通过编组/选择状态并将结果字符串的字节数据编码为整数来转换为一个整数值)。setstate
(state)将编码器的状态设为 state*。 *state 必须为
getstate()
所返回的一个编码器状态。
IncrementalDecoder 对象
IncrementalDecoder
类用来对一个输入进行分步解码。 它定义了以下方法,每个增量式解码器都必须定义这些方法以便与 Python 编解码器注册表相兼容。
class codecs.IncrementalDecoder
(errors=’strict’)
IncrementalDecoder
实例的构造器。
所有增量式解码器必须提供此构造器接口。 它们可以自由地添加额外的关键字参数,但只有在这里定义的参数才会被 Python 编解码器注册表所使用。
IncrementalDecoder
可以通过提供 errors 关键字参数来实现不同的错误处理方案。
errors 参数将被赋值给一个同名的属性。 通过对此属性赋值就可以在 IncrementalDecoder
对象的生命期内在不同的错误处理策略之间进行切换。
decode
(object[, final])解码 object (会将解码器的当前状态纳入考虑) 并返回已解码的结果对象。 如果这是对
decode()
的最终调用则 final 必须为真值(默认为假值)。 如果 final 为真值则解码器必须对输入进行完全解码并且必须 刷新所有缓冲区。 如果这无法做到(例如由于在输入结束时字节串序列不完整)则它必须像在无状态的情况下那样初始化错误处理(这可能引发一个异常)。reset
()将解码器重置为初始状态。
getstate
()返回解码器的当前状态。 这必须为一个二元组,第一项必须是包含尚未解码的输入的缓冲区。 第二项必须为一个整数,可以表示附加状态信息。 (实现应当确保
0
是最常见的附加状态信息。) 如果此附加状态信息为0
则必须可以将解码器设为没有已缓冲输入并且以0
作为附加状态信息,以便将先前已缓冲的输入馈送到解码器使其返回到先前的状态而不产生任何输出。 (比整数更复杂的附加状态信息可以通过编组/选择状态信息并将结果字符串的字节数据编码为整数来转换为一个整数值。)setstate
(state)将解码器的状态设为 state*。 *state 必须为
getstate()
所返回的一个解码器状态。
流式的编码和解码
StreamWriter
和 StreamReader
类提供了一些泛用工作接口,可被用来非常方便地实现新的编码格式子模块。
StreamWriter 对象
StreamWriter
类是 Codec
的子类,它定义了以下方法,每个流式写入器都必须定义这些方法以便与 Python 编解码器注册表相兼容。
class codecs.StreamWriter
(stream, errors=’strict’)
StreamWriter
实例的构造器。
所有流式写入器必须提供此构造器接口。 它们可以自由地添加额外的关键字参数,但只有在这里定义的参数才会被 Python 编解码器注册表所使用。
stream 参数必须为一个基于特定编解码器打开用于写入文本或二进制数据的文件类对象。
StreamWriter
可以通过提供 errors 关键字参数来实现不同的错误处理方案。
errors 参数将被赋值给一个同名的属性。 通过对此属性赋值就可以在 StreamWriter
对象的生命期内在不同的错误处理策略之间进行切换。
write
(object)将编码后的对象内容写入到流。
writelines
(list)将拼接后的字符串列表写入到流(可能通过重用
write()
方法)。 标准的字节到字节编解码器不支持此方法。reset
()重置用于保持内部状态的编解码器缓冲区。
调用此方法应当确保在干净的状态下放入输出数据,以允许直接添加新的干净数据而无须重新扫描整个流来恢复状态。
除了上述的方法,StreamWriter
还必须继承来自下层流的所有其他方法和属性。
StreamReader 对象
StreamReader
类是 Codec
的子类,它定义了以下方法,每个流式读取器都必须定义这些方法以便与 Python 编解码器注册表相兼容。
class codecs.StreamReader
(stream, errors=’strict’)
StreamReader
实例的构造器。
所有流式读取器必须提供此构造器接口。 它们可以自由地添加额外的关键字参数,但只有在这里定义的参数才会被 Python 编解码器注册表所使用。
stream 参数必须为一个基于特定编解码器打开用于读取文本或二进制数据的文件类对象。
StreamReader
可以通过提供 errors 关键字参数来实现不同的错误处理方案。
errors 参数将被赋值给一个同名的属性。 通过对此属性赋值就可以在 StreamReader
对象的生命期内在不同的错误处理策略之间进行切换。
errors 参数所允许的值集合可以使用 register_error()
来扩展。
read
([size[, chars[, firstline]]])解码来自流的数据并返回结果对象。
chars 参数指明要返回的解码后码位或字节数量。
read()
方法绝不会返回超出请求数量的数据,但如果可用数量不足,它可能返回少于请求数量的数据。size 参数指明要读取并解码的已编码字节或码位的最大数量近似值。 解码器可以适当地修改此设置。 默认值 -1 表示尽可能多地读取并解码。 此形参的目的是防止一次性解码过于巨大的文件。
firstline 旗标指明如果在后续行发生解码错误,则仅返回第一行就足够了。
此方法应当使用“贪婪”读取策略,这意味着它应当在编码格式定义和给定大小所允许的情况下尽可能多地读取数据,例如,如果在流上存在可选的编码结束或状态标记,这些内容也应当被读取。
readline
([size[, keepends]])从输入流读取一行并返回解码后的数据。
如果给定了 size,则将其作为 size 参数传递给流的
read()
方法。如果 keepends 为假值,则行结束符将从返回的行中去除。
readlines
([sizehint[, keepends]])从输入流读取所有行并将其作为一个行列表返回。
行结束符会使用编解码器的
decode()
方法来实现,并且如果 keepends 为真值则会将其包含在列表条目中。如果给定了 sizehint*,则将其作为 *size 参数传递给流的
read()
方法。reset
()重置用于保持内部状态的编解码器缓冲区。
请注意不应当对流进行重定位。 使用此方法的主要目的是为了能够从解码错误中恢复。
除了上述的方法,StreamReader
还必须继承来自下层流的所有其他方法和属性。
StreamReaderWriter 对象
StreamReaderWriter
是一个方便的类,允许对同时工作于读取和写入模式的流进行包装。
其设计使得开发者可以使用 lookup()
函数所返回的工厂函数来构造实例。
class codecs.StreamReaderWriter
(stream, Reader, Writer, errors=’strict’)
创建一个 StreamReaderWriter
实例。 stream 必须为一个文件类对象。 Reader 和 Writer 必须为分别提供了 StreamReader
和 StreamWriter
接口的工厂函数或类。 错误处理通过与流式读取器和写入器所定义的相同方式来完成。
StreamReaderWriter
实例定义了 StreamReader
和 StreamWriter
类的组合接口。 它们还继承了来自下层流的所有其他方法和属性。
StreamRecoder 对象
StreamRecoder
将数据从一种编码格式转换为另一种,这对于处理不同编码环境的情况有时会很有用。
其设计使得开发者可以使用 lookup()
函数所返回的工厂函数来构造实例。
class codecs.StreamRecoder
(stream, encode, decode, Reader, Writer, errors=’strict’)
创建一个实现了双向转换的 StreamRecoder
实例: encode 和 decode 工作于前端 — 对代码可见的数据调用 read()
和 write()
,而 Reader 和 Writer 工作于后端 — stream 中的数据。
你可以使用这些对象来进行透明转码,例如从 Latin-1 转为 UTF-8 以及反向转换。
stream 参数必须为一个文件类对象。
encode 和 decode 参数必须遵循 Codec
接口。 Reader 和 Writer 必须为分别提供了 StreamReader
和 StreamWriter
接口对象的工厂函数或类。
错误处理通过与流式读取器和写入器所定义的相同方式来完成。
StreamRecoder
实例定义了 StreamReader
和 StreamWriter
类的组合接口。 它们还继承了来自下层流的所有其他方法和属性。
编码格式与 Unicode
字符串在系统内部存储为 0x0
–0x10FFFF
范围内的码位序列。 (请参阅 PEP 393 了解有关实现的详情。) 一旦字符串对象要在 CPU 和内存以外使用,字节的大小端顺序和字节数组的存储方式就成为一个关键问题。 如同使用其他编解码器一样,将字符串序列化为字节序列被称为 编码,而从字节序列重建字符串被称为 解码。 存在许多不同的文本序列化编解码器,它们被统称为 文本编码。
最简单的文本编码格式 (称为 'latin-1'
或 'iso-8859-1'
) 将码位 0—255 映射为字节值 0x0
–0xff
,这意味着包含 U+00FF
以上码位的字符串对象无法使用此编解码器进行编码。 这样做将引发 UnicodeEncodeError
,其形式类似下面这样(不过详细的错误信息可能会有所不同): UnicodeEncodeError: 'latin-1' codec can't encode character '\u1234' in position 3: ordinal not in range(256)
。
还有另外一组编码格式(所谓的字符映射编码)会选择全部 Unicode 码位的不同子集并设定如何将这些码位映射为字节值 0x0
–0xff
。 要查看这是如何实现的,只需简单地打开相应源码例如 encodings/cp1252.py
(这是一个主要在 Windows 上使用的编码格式)。 其中会有一个包含 256 个字符的字符串常量,指明每个字符所映射的字节值。
所有这些编码格式只能对 Unicode 所定义的 1114112 个码位中的 256 个进行编码。 一种能够存储每个 Unicode 码位的简单而直接的办法就是将每个码位存储为四个连续的字节。 存在两种不同的可能性:以大端序存储或以小端序存储。 这两种编码格式分别被称为 UTF-32-BE
和 UTF-32-LE
。 它们的缺点可以举例说明:如果你在一台小端序的机器上使用 UTF-32-BE
则你将必须在编码和解码时翻转字节。 UTF-32
避免了这个问题:字节的排列将总是使用自然顺序。 当这些字节被具有不同字节顺序的 CPU 读取时,则必须进行字节翻转。 为了能够检测 UTF-16
或 UTF-32
字节序列的大小端序,可以使用所谓的 BOM (“字节顺序标记”)。 这对应于 Unicode 字符 U+FEFF
。 此字符可添加到每个 UTF-16
或 UTF-32
字节序列的开头。 此字符的字节翻转版本 (0xFFFE
) 是一个不可出现于 Unicode 文本中的非法字符。 因此当发现一个 UTF-16
或 UTF-32
字节序列的首个字符是 U+FFFE
时,就必须在解码时进行字节翻转。 不幸的是字符 U+FEFF
还有第二个含义 ZERO WIDTH NO-BREAK SPACE
: 即宽度为零并且不允许用来拆分单词的字符。 它可以被用来为语言分析算法提供提示。 在 Unicode 4.0 中用 U+FEFF
表示 ZERO WIDTH NO-BREAK SPACE
已被弃用(改用 U+2060
(WORD JOINER
) 负责此任务)。 然而 Unicode 软件仍然必须能够处理 U+FEFF
的两个含义:作为 BOM 它被用来确定已编码字节的存储布局,并在字节序列被解码为字符串后将其去除;作为 ZERO WIDTH NO-BREAK SPACE
它是一个普通字符,将像其他字符一样被解码。
There’s another encoding that is able to encode the full range of Unicode characters: UTF-8. UTF-8 is an 8-bit encoding, which means there are no issues with byte order in UTF-8. Each byte in a UTF-8 byte sequence consists of two parts: marker bits (the most significant bits) and payload bits. The marker bits are a sequence of zero to four 1
bits followed by a 0
bit. Unicode characters are encoded like this (with x being payload bits, which when concatenated give the Unicode character):
范围 | 编码 |
---|---|
U-00000000 … U-0000007F |
0xxxxxxx |
U-00000080 … U-000007FF |
110xxxxx 10xxxxxx |
U-00000800 … U-0000FFFF |
1110xxxx 10xxxxxx 10xxxxxx |
U-00010000 … U-0010FFFF |
11110xxx 10xxxxxx 10xxxxxx 10xxxxxx |
Unicode 字符最不重要的一个位就是最右侧的二进制位 x。
由于 UTF-8 是一种 8 位编码格式,因此 BOM 是不必要的,并且已编码字符串中的任何 U+FEFF
字符(即使是作为第一个字符)都会被视为是 ZERO WIDTH NO-BREAK SPACE
。
在没有外部信息的情况下,就不可能毫无疑义地确定一个字符串使用了何种编码格式。 每种字符映射编码格式都可以解码任意的随机字节序列。 然而对 UTF-8 来说这却是不可能的,因为 UTF-8 字节序列具有不允许任意字节序列的特别结构。 为了提升 UTF-8 编码检测的可靠性,Microsoft 发明了一种 UTF-8 变体形式 (Python 2.5 称之为 "utf-8-sig"
) 专门用于其 Notepad 程序:在任何 Unicode 字符在被写入文件之前,会先写入一个 UTF-8 编码的 BOM (它看起来是这样一个字节序列: 0xef
, 0xbb
, 0xbf
)。 由于任何字符映射编码后的文件都不大可能以这些字节值开头(例如它们会映射为
LATIN SMALL LETTER I WITH DIAERESIS
RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
INVERTED QUESTION MARK
对于 iso-8859-1 编码格式来说),这提升了根据字节序列来正确猜测 utf-8-sig
编码格式的成功率。 所以在这里 BOM 的作用并不是帮助确定生成字节序列所使用的字节顺序,而是作为帮助猜测编码格式的记号。 在进行编码时 utf-8-sig 编解码器将把 0xef
, 0xbb
, 0xbf
作为头三个字节写入文件。 在进行解码时 utf-8-sig
将跳过这三个字节,如果它们作为文件的头三个字节出现的话。 在 UTF-8 中并不推荐使用 BOM,通常应当避免它们的出现。
标准编码
Python 自带了许多内置的编解码器,它们的实现或者是通过 C 函数,或者是通过映射表。 以下表格是按名称排序的编解码器列表,并提供了一些常见别名以及编码格式通常针对的语言。 别名和语言列表都不是详尽无遗的。 请注意仅有大小写区别或使用连字符替代下划线的拼写形式也都是有效的别名;因此,'utf-8'
是 'utf_8'
编解码器的有效别名。
CPython implementation detail: 有些常见编码格式可以绕过编解码器查找机制来提升性能。 这些优化机会对于 CPython 来说仅能通过一组有限的别名(大小写不敏感)来识别:utf-8, utf8, latin-1, latin1, iso-8859-1, iso8859-1, mbcs (Windows 专属), ascii, us-ascii, utf-16, utf16, utf-32, utf32, 也包括使用下划线替代连字符的的形式。 使用这些编码格式的其他别名可能会导致更慢的执行速度。
在 3.6 版更改: 可识别针对 us-ascii 的优化机会。
许多字符集都支持相同的语言。 它们在个别字符(例如是否支持 EURO SIGN 等)以及给字符所分配的码位方面存在差异。 特别是对于欧洲语言来说,通常存在以下几种变体:
- 某个 ISO 8859 编码集
- 某个 Microsoft Windows 编码页,通常是派生自某个 8859 编码集,但会用附加的图形字符来替换控制字符。
- 某个 IBM EBCDIC 编码页
- 某个 IBM PC 编码页,通常会兼容 ASCII
编码 | 别名 | 语言 |
---|---|---|
ascii | 646, us-ascii | 英语 |
big5 | big5-tw, csbig5 | 繁体中文 |
big5hkscs | big5-hkscs, hkscs | 繁体中文 |
cp037 | IBM037, IBM039 | 英语 |
cp273 | 273, IBM273, csIBM273 | 德语3.4 新版功能. |
cp424 | EBCDIC-CP-HE, IBM424 | 希伯来语 |
cp437 | 437, IBM437 | 英语 |
cp500 | EBCDIC-CP-BE, EBCDIC-CP-CH, IBM500 | 西欧 |
cp720 | 阿拉伯语 | |
cp737 | 希腊语 | |
cp775 | IBM775 | 波罗的海语言 |
cp850 | 850, IBM850 | 西欧 |
cp852 | 852, IBM852 | 中欧和东欧 |
cp855 | 855, IBM855 | 保加利亚语,白俄罗斯语,马其顿语,俄语,塞尔维亚语 |
cp856 | 希伯来语 | |
cp857 | 857, IBM857 | 土耳其语 |
cp858 | 858, IBM858 | 西欧 |
cp860 | 860, IBM860 | 葡萄牙语 |
cp861 | 861, CP-IS, IBM861 | 冰岛语 |
cp862 | 862, IBM862 | 希伯来语 |
cp863 | 863, IBM863 | 加拿大语 |
cp864 | IBM864 | 阿拉伯语 |
cp865 | 865, IBM865 | 丹麦语/挪威语 |
cp866 | 866, IBM866 | 俄语 |
cp869 | 869, CP-GR, IBM869 | 希腊语 |
cp874 | 泰语 | |
cp875 | 希腊语 | |
cp932 | 932, ms932, mskanji, ms-kanji | 日语 |
cp949 | 949, ms949, uhc | 韩语 |
cp950 | 950, ms950 | 繁体中文 |
cp1006 | 乌尔都语 | |
cp1026 | ibm1026 | 土耳其语 |
cp1125 | 1125, ibm1125, cp866u, ruscii | 乌克兰语3.4 新版功能. |
cp1140 | ibm1140 | 西欧 |
cp1250 | windows-1250 | 中欧和东欧 |
cp1251 | windows-1251 | 保加利亚语,白俄罗斯语,马其顿语,俄语,塞尔维亚语 |
cp1252 | windows-1252 | 西欧 |
cp1253 | windows-1253 | 希腊语 |
cp1254 | windows-1254 | 土耳其语 |
cp1255 | windows-1255 | 希伯来语 |
cp1256 | windows-1256 | 阿拉伯语 |
cp1257 | windows-1257 | 波罗的海语言 |
cp1258 | windows-1258 | 越南语 |
euc_jp | eucjp, ujis, u-jis | 日语 |
euc_jis_2004 | jisx0213, eucjis2004 | 日语 |
euc_jisx0213 | eucjisx0213 | 日语 |
euc_kr | euckr, korean, ksc5601, ks_c-5601, ks_c-5601-1987, ksx1001, ks_x-1001 | 韩语 |
gb2312 | chinese, csiso58gb231280, euc-cn, euccn, eucgb2312-cn, gb2312-1980, gb2312-80, iso-ir-58 | 简体中文 |
gbk | 936, cp936, ms936 | 统一汉语 |
gb18030 | gb18030-2000 | 统一汉语 |
hz | hzgb, hz-gb, hz-gb-2312 | 简体中文 |
iso2022_jp | csiso2022jp, iso2022jp, iso-2022-jp | 日语 |
iso2022_jp_1 | iso2022jp-1, iso-2022-jp-1 | 日语 |
iso2022_jp_2 | iso2022jp-2, iso-2022-jp-2 | 日语,韩语,简体中文,西欧,希腊语 |
iso2022_jp_2004 | iso2022jp-2004, iso-2022-jp-2004 | 日语 |
iso2022_jp_3 | iso2022jp-3, iso-2022-jp-3 | 日语 |
iso2022_jp_ext | iso2022jp-ext, iso-2022-jp-ext | 日语 |
iso2022_kr | csiso2022kr, iso2022kr, iso-2022-kr | 韩语 |
latin_1 | iso-8859-1, iso8859-1, 8859, cp819, latin, latin1, L1 | 西欧 |
iso8859_2 | iso-8859-2, latin2, L2 | 中欧和东欧 |
iso8859_3 | iso-8859-3, latin3, L3 | 世界语,马耳他语 |
iso8859_4 | iso-8859-4, latin4, L4 | 波罗的海语言 |
iso8859_5 | iso-8859-5, cyrillic | 保加利亚语,白俄罗斯语,马其顿语,俄语,塞尔维亚语 |
iso8859_6 | iso-8859-6, arabic | 阿拉伯语 |
iso8859_7 | iso-8859-7, greek, greek8 | 希腊语 |
iso8859_8 | iso-8859-8, hebrew | 希伯来语 |
iso8859_9 | iso-8859-9, latin5, L5 | 土耳其语 |
iso8859_10 | iso-8859-10, latin6, L6 | 北欧语言 |
iso8859_11 | iso-8859-11, thai | 泰语 |
iso8859_13 | iso-8859-13, latin7, L7 | 波罗的海语言 |
iso8859_14 | iso-8859-14, latin8, L8 | 凯尔特语 |
iso8859_15 | iso-8859-15, latin9, L9 | 西欧 |
iso8859_16 | iso-8859-16, latin10, L10 | 东南欧 |
johab | cp1361, ms1361 | 韩语 |
koi8_r | 俄语 | |
koi8_t | 塔吉克3.5 新版功能. | |
koi8_u | 乌克兰语 | |
kz1048 | kz_1048, strk1048_2002, rk1048 | 哈萨克语3.5 新版功能. |
mac_cyrillic | maccyrillic | 保加利亚语,白俄罗斯语,马其顿语,俄语,塞尔维亚语 |
mac_greek | macgreek | 希腊语 |
mac_iceland | maciceland | 冰岛语 |
mac_latin2 | maclatin2, maccentraleurope, mac_centeuro | 中欧和东欧 |
mac_roman | macroman, macintosh | 西欧 |
mac_turkish | macturkish | 土耳其语 |
ptcp154 | csptcp154, pt154, cp154, cyrillic-asian | 哈萨克语 |
shift_jis | csshiftjis, shiftjis, sjis, s_jis | 日语 |
shift_jis_2004 | shiftjis2004, sjis_2004, sjis2004 | 日语 |
shift_jisx0213 | shiftjisx0213, sjisx0213, s_jisx0213 | 日语 |
utf_32 | U32, utf32 | 所有语言 |
utf_32_be | UTF-32BE | 所有语言 |
utf_32_le | UTF-32LE | 所有语言 |
utf_16 | U16, utf16 | 所有语言 |
utf_16_be | UTF-16BE | 所有语言 |
utf_16_le | UTF-16LE | 所有语言 |
utf_7 | U7, unicode-1-1-utf-7 | 所有语言 |
utf_8 | U8, UTF, utf8, cp65001 | 所有语言 |
utf_8_sig | 所有语言 |
在 3.4 版更改: utf-16* 和 utf-32* 编码器将不再允许编码代理码位 (U+D800
–U+DFFF
)。 utf-32* 解码器将不再解码与代理码位相对应的字节序列。
在 3.8 版更改: cp65001
现在是 utf_8
的一个别名。
Python 专属的编码格式
有一些预定义编解码器是 Python 专属的,因此它们在 Python 之外没有意义。 这些编解码器按其所预期的输入和输出类型在下表中列出(请注意虽然文本编码是编解码器最常见的使用场景,但下层的编解码器架构支持任意数据转换而不仅是文本编码)。 对于非对称编解码器,该列描述的含义是编码方向。
文字编码
以下编解码器提供了 str
到 bytes
的编码和 bytes-like object 到 str
的解码,类似于 Unicode 文本编码。
编码 | 别名 | 含意 |
---|---|---|
idna | 实现 RFC 3490。仅支持 errors=’strict’ 。 |
|
mbcs | ansi, dbcs | Windows 专属:根据 ANSI 代码页(CP_ACP)对操作数进行编码。 |
oem | Windows 专属:根据 OEM 代码页(CP_OEMCP)对操作数进行编码。3.6 新版功能. | |
palmos | PalmOS 3.5 的编码格式 | |
punycode | 实现 RFC 3492。 不支持有状态编解码器。 | |
raw_unicode_escape | Latin-1 编码格式附带对其他码位以 \uXXXX 和 \UXXXXXXXX 进行编码。 现有反斜杠不会以任何方式转义。 它被用于 Python 的 pickle 协议。 |
|
undefined | 所有转换都将引发异常,甚至对空字符串也不例外。 错误处理方案会被忽略。 | |
unicode_escape | 适合用于以 ASCII 编码的 Python 源代码中的 Unicode 字面值内容的编码格式,但引号不会被转义。 对 Latin-1 源代码进行解码。 请注意 Python 源代码实际上默认使用 UTF-8。 |
在 3.8 版更改: “unicode_internal” 编解码器已被移除。
二进制转换
以下编解码器提供了二进制转换: bytes-like object 到 bytes
的映射。 它们不被 bytes.decode()
所支持(该方法只生成 str
类型的输出)。
编码 | 别名 | 含意 | 编码器/解码器 |
---|---|---|---|
base64_codec | base64, base_64 | 将操作数转换为多行 MIME base64 (结果总是包含一个末尾的 ‘\n’ )在 3.4 版更改: 接受任意 bytes-like object 作为输入用于编码和解码 |
base64.encodebytes() / base64.decodebytes() |
bz2_codec | bz2 | 使用bz2压缩操作数 | bz2.compress() / bz2.decompress() |
hex_codec | hex | 将操作数转换为十六进制表示,每个字节有两位数 | binascii.b2a_hex() / binascii.a2b_hex() |
quopri_codec | quopri, quotedprintable, quoted_printable | 将操作数转换为 MIME 带引号的可打印数据 | quopri.encode() 且 quotetabs=True / quopri.decode() |
uu_codec | uu | 使用uuencode转换操作数 | uu.encode() / uu.decode() |
zlib_codec | zip, zlib | 使用gzip压缩操作数 | zlib.compress() / zlib.decompress() |
除了 字节类对象,'base64_codec'
也接受仅包含 ASCII 的 str
实例用于解码
3.2 新版功能: 恢复二进制转换。
在 3.4 版更改: 恢复二进制转换的别名。
文字转换
以下编解码器提供了文本转换: str
到 str
的映射。 它不被 str.encode()
所支持(该方法只生成 bytes
类型的输出)。
编码 | 别名 | 含意 |
---|---|---|
rot_13 | rot13 | 返回操作数的凯撒密码加密结果 |
3.2 新版功能: 恢复 rot_13
文本转换。
在 3.4 版更改: 恢复 rot13
别名。
encodings.idna
—- 应用程序中的国际化域名
此模块实现了 RFC 3490 (应用程序中的国际化域名) 和 RFC 3492 (Nameprep: 用于国际化域名 (IDN) 的 Stringprep 配置文件)。 它是在 punycode
编码格式和 stringprep
的基础上构建的。
如果你需要来自 RFC 5891 和 RFC 5895 的 IDNA 2008 标准,请使用第三方 idna 模块 https://pypi.org/project/idna/
这些 RFC 共同定义了一个在域名中支持非 ASCII 字符的协议。 一个包含非 ASCII 字符的域名 (例如 www.Alliancefrançaise.nu
) 会被转换为兼容 ASCII 的编码格式 (简称 ACE,例如 www.xn--alliancefranaise-npb.nu
)。 随后此域名的 ACE 形式可以用于所有由于特定协议而不允许使用任意字符的场合,例如 DNS 查询,HTTP Host 字段等等。 此转换是在应用中进行的;如有可能将对用户可见:应用应当透明地将 Unicode 域名标签转换为线上的 IDNA,并在 ACE 标签被呈现给用户之前将其转换回 Unicode。
Python 以多种方式支持这种转换: idna
编解码器执行 Unicode 和 ACE 之间的转换,基于在 section 3.1 of RFC 3490 中定义的分隔字符将输入字符串拆分为标签,再根据需要将每个标签转换为 ACE,相反地又会基于 .
分隔符将输入字节串拆分为标签,再将找到的任何 ACE 标签转换为 Unicode。 此外,socket
模块可透明地将 Unicode 主机名转换为 ACE,以便应用在将它们传给 socket 模块时无须自行转换主机名。 除此之外,许多包含以主机名作为函数参数的模块例如 http.client
和 ftplib
都接受 Unicode 主机名(并且 http.client
也会在 Host 字段中透明地发送 IDNA 主机名,如果它需要发送该字段的话)。
当从线路接收主机名时(例如反向名称查找),到 Unicode 的转换不会自动被执行:希望向用户提供此种主机名的应用应当将它们解码为 Unicode。
encodings.idna
模块还实现了 nameprep 过程,该过程会对主机名执行特定的规范化操作,以实现国际域名的大小写不敏感特性与合并相似的字符。 如果有需要可以直接使用 nameprep 函数。
encodings.idna.nameprep
(label)
返回 label 经过名称处理操作的版本。 该实现目前基于查询字符串,因此 AllowUnassigned
为真值。
encodings.idna.ToASCII
(label)
将标签转换为 ASCII,规则定义见 RFC 3490。 UseSTD3ASCIIRules
预设为假值。
encodings.idna.ToUnicode
(label)
将标签转换为 Unicode,规则定义见 RFC 3490。
encodings.mbcs
—- Windows ANSI代码页
此模块实现ANSI代码页(CP_ACP)。
Availability: 仅Windows可用
在 3.3 版更改: 支持任何错误处理
在 3.2 版更改: 在 3.2 版之前, errors 参数会被忽略;总是会使用 'replace'
进行编码,并使用 'ignore'
进行解码。
encodings.utf_8_sig
—- 带BOM签名的UTF-8编解码器
此模块实现了 UTF-8 编解码器的一个变种:在编码时将把 UTF-8 已编码 BOM 添加到 UTF-8 编码字节数据的开头。 对于有状态编码器此操作只执行一次(当首次写入字节流时)。 在解码时将跳过数据开头作为可选项的 UTF-8 已编码 BOM。
数据类型
Python也提供一些内置数据类型,特别是,dict
、 list
、set
、frozenset
、以及 tuple
。str
这个类是用来存储Unicode字符串的,而 bytes
和 bytearray
这两个类是用来存储二进制数据的。
本章包含以下模块的文档:
datetime
—- 基本日期和时间类型- 感知型对象和简单型对象
- 常量
- 有效的类型
- 通用的特征属性
- 确定一个对象是感知型还是简单型
timedelta
类对象- class:timedelta 用法示例
date
对象- class:date 用法示例
datetime
对象- 用法示例:
datetime
- 用法示例:
time
对象- 用法示例:
time
- 用法示例:
tzinfo
对象timezone
对象strftime()
和strptime()
的行为strftime()
和strptime()
Format Codes- 技术细节
zoneinfo
—- IANA 时区支持- 使用
ZoneInfo
- 数据源
- 配置数据源
- 编译时配置
- 环境配置
- 运行时配置
- 配置数据源
ZoneInfo
类- 字符串表示
- 封存序列化
- 函数
- 全局变量
- 异常与警告
- 使用
calendar
—- 日历相关函数collections
—- 容器数据类型ChainMap
对象ChainMap
例子和方法
Counter
对象deque
对象deque
用法
defaultdict
对象defaultdict
例子
namedtuple()
命名元组的工厂函数OrderedDict
对象OrderedDict
例子和用法
UserDict
对象UserList
对象UserString
对象
collections.abc
—- 容器的抽象基类- 容器抽象基类
- Collections Abstract Base Classes — Detailed Descriptions
- Examples and Recipes
heapq
—- 堆队列算法- 基本示例
- 优先队列实现说明
- 理论
bisect
—- 数组二分查找算法- 性能说明
- 搜索有序列表
- 例子
array
—- 高效的数值数组weakref
—- 弱引用- 弱引用对象
- 示例
- 终结器对象
- 比较终结器与
__del__()
方法
types
—- 动态类型创建和内置类型名称- 动态类型创建
- 标准解释器类型
- 附加工具类和函数
- 协程工具函数
copy
—- 浅层 (shallow) 和深层 (deep) 复制操作pprint
—- 数据美化输出- PrettyPrinter 对象
- 示例
reprlib
—- 另一种repr()
实现- Repr 对象
- 子类化 Repr 对象
enum
—- 对枚举的支持- 模块内容
- 创建 Enum
- 枚举成员及其属性的编程访问
- 重复的枚举成员和值
- 确保唯一枚举值
- 使用自动设定的值
- 迭代
- 比较运算
- 允许的枚举成员和属性
- 受限的 Enum 子类化
- 封存
- 功能性 API
- 派生的枚举
- IntEnum
- IntFlag
- 旗标
- 其他事项
- 何时使用
__new__()
与__init__()
- 有趣的示例
- 省略值
- 使用
auto
- 使用
object
- 使用描述性字符串
- 使用自定义的
__new__()
- 使用
- OrderedEnum
- DuplicateFreeEnum
- Planet
- TimePeriod
- 省略值
- 各种枚举有何区别?
- 枚举类
- 枚举成员(即实例)
- 细节要点
- 支持的
__dunder__
名称 - 支持的
_sunder_
名称 - _Private__names
Enum
成员类型Enum
类和成员的布尔值- 带有方法的
Enum
类 - 组合
Flag
的成员
- 支持的
graphlib
—- 操作类似图的结构的功能- 异常
datetime
—- 基本日期和时间类型
源代码:Lib/datetime.py
datetime
模块提供用于处理日期和时间的类。
在支持日期时间数学运算的同时,实现的关注点更着重于如何能够更有效地解析其属性用于格式化输出和数据操作。
感知型对象和简单型对象
日期和时间对象可以根据它们是否包含时区信息而分为“感知型”和“简单型”两类。
充分掌握应用性算法和政治性时间调整信息例如时区和夏令时的情况下,一个 感知型 对象就能相对于其他感知型对象来精确定位自身时间点。 感知型对象是用来表示一个没有解释空间的固定时间点。
简单型 对象没有包含足够多的信息来无歧义地相对于其他 date/time 对象来定位自身时间点。 不论一个简单型对象所代表的是世界标准时间(UTC)、当地时间还是某个其他时区的时间完全取决于具体程序,就像一个特定数字所代表的是米、英里还是质量完全取决于具体程序一样。 简单型对象更易于理解和使用,代价则是忽略了某些现实性考量。
对于要求感知型对象的应用,datetime
和 time
对象具有一个可选的时区信息属性 tzinfo
,它可被设为抽象类 tzinfo
的子类的一个实例。 这些 tzinfo
对象会捕获与 UTC 时间的差值、时区名称以及夏令时是否生效等信息。
datetime
模块只提供了一个具体的 tzinfo
类,即 timezone
类。 timezone
类可以表示具有相对于 UTC 的固定时差的简单时区,例如 UTC 本身或北美的 EST 和 EDT 时区等。 支持时间的详细程度取决于具体的应用。 世界各地的时间调整规则往往是政治性多于合理性,经常会发生变化,除了 UTC 之外并没有一个能适合所有应用的标准。
常量
The datetime
module exports the following constants:
datetime.MINYEAR
date
或者 datetime
对象允许的最小年份。 常量 MINYEAR
是 1
。
datetime.MAXYEAR
date
或 datetime
对象允许最大的年份。常量 MAXYEAR
是 9999
。
有效的类型
classdatetime.date
一个理想化的简单型日期,它假设当今的公历在过去和未来永远有效。 属性: year
, month
, and day
。
classdatetime.time
一个独立于任何特定日期的理想化时间,它假设每一天都恰好等于 246060 秒。 (这里没有“闰秒”的概念。) 包含属性: hour
, minute
, second
, microsecond
和 tzinfo
。
classdatetime.datetime
日期和时间的结合。属性:year
, month
, day
, hour
, minute
, second
, microsecond
, and tzinfo
.
classdatetime.timedelta
表示两个 date
对象或 time
对象,或者 datetime
对象之间的时间间隔,精确到微秒。
classdatetime.tzinfo
一个描述时区信息对象的抽象基类。 用来给 datetime
和 time
类提供自定义的时间调整概念(例如处理时区和/或夏令时)。
classdatetime.timezone
一个实现了 tzinfo
抽象基类的子类,用于表示相对于 世界标准时间(UTC)的偏移量。
3.2 新版功能.
这些类型的对象都是不可变的。
子类关系
object
timedelta
tzinfo
timezone
time
date
datetime
通用的特征属性
date
, datetime
, time
和 timezone
类型共享这些通用特性:
- 这些类型的对象都是不可变的。
- 这些类型的对象是可哈希的,这意味着它们可被作为字典的键。
- 这些类型的对象支持通过
pickle
模块进行高效的封存。
确定一个对象是感知型还是简单型
date
类型的对象都是简单型的。
time
或 datetime
类型的对象可以是感知型或者简单型。
一个 datetime
对象 d 在以下条件同时成立时将是感知型的:
d.tzinfo
不为None
d.tzinfo.utcoffset(d)
不返回None
在其他情况下,d 将是简单型的。
一个 time
对象 t 在以下条件同时成立时将是感知型的:
t.tzinfo
不为None
t.tzinfo.utcoffset(None)
不返回None
。
在其他情况下,t 将是简单型的。
感知型和简单型之间的区别不适用于 timedelta
对象。
timedelta
类对象
timedelta
对象表示两个 date 或者 time 的时间间隔。
classdatetime.timedelta
(days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0)
所有参数都是可选的并且默认为 0
。 这些参数可以是整数或者浮点数,也可以是正数或者负数。
只有 days, seconds 和 microseconds 会存储在内部。 参数单位的换算规则如下:
- 1毫秒会转换成1000微秒。
- 1分钟会转换成60秒。
- 1小时会转换成3600秒。
- 1星期会转换成7天。
日期、秒、微秒都是标准化的,所以它们的表达方式也是唯一的,例:
0 <= microseconds < 1000000
0 <= seconds < 3600*24
(一天的秒数)-999999999 <= days <= 999999999
下面的例子演示了如何对 days, seconds 和 microseconds 以外的任意参数执行“合并”操作并标准化为以上三个结果属性:
>>>from datetime import timedelta
>>> delta = timedelta(
... days=50,
... seconds=27,
... microseconds=10,
... milliseconds=29000,
... minutes=5,
... hours=8,
... weeks=2
...)
>>># Only days, seconds, and microseconds remain
>>> delta
datetime.timedelta(days=64, seconds=29156, microseconds=10)
在有任何参数为浮点型并且 microseconds 值为小数的情况下,从所有参数中余下的微秒数将被合并,并使用四舍五入偶不入奇的规则将总计值舍入到最接近的整数微秒值。 如果没有任何参数为浮点型的情况下,则转换和标准化过程将是完全精确的(不会丢失信息)。
如果标准化后的 days 数值超过了指定范围,将会抛出 OverflowError
异常。
请注意对负数值进行标准化的结果可能会令人感到惊讶。 例如:
>>>from datetime import timedelta
>>> d = timedelta(microseconds=-1)
>>>(d.days, d.seconds, d.microseconds)
(-1,86399,999999)
类属性:
timedelta.min
The most negative timedelta
object, timedelta(-999999999)
.
timedelta.max
The most positive timedelta
object, timedelta(days=999999999, hours=23, minutes=59, seconds=59, microseconds=999999)
.
timedelta.resolution
两个不相等的 timedelta
类对象最小的间隔为 timedelta(microseconds=1)
。
需要注意的是,因为标准化的缘故,timedelta.max
> -timedelta.min
,-timedelta.max
不可以表示一个 timedelta
类对象。
实例属性(只读):
属性 | 值 |
---|---|
days |
-999999999 至 999999999 ,含999999999 |
seconds |
0 至 86399,包含86399 |
microseconds |
0 至 999999,包含999999 |
支持的运算:
运算 | 结果: |
---|---|
t1 = t2 + t3 |
t2 和 t3 的和。 运算后 t1-t2 == t3 and t1-t3 == t2 必为真值。(1) |
t1 = t2 - t3 |
t2 减 t3 的差。 运算后 t1 == t2 - t3 and t2 == t1 + t3 必为真值。 (1)(6) |
t1 = t2 *i or t1 = i* t2 |
乘以一个整数。运算后假如 i != 0 则 t1 // i == t2 必为真值。 |
In general, t1 i == *t1** (i-1) + *t1 is true. (1) | |
t1 = t2 *f or t1 = f* t2 |
乘以一个浮点数,结果会被舍入到 timedelta 最接近的整数倍。 精度使用四舍五偶入奇不入规则。 |
f = t2 / t3 |
总时间 t2 除以间隔单位 t3 (3)。 返回一个 float 对象。 |
t1 = t2 / f or t1 = t2 / i |
除以一个浮点数或整数。 结果会被舍入到 timedelta 最接近的整数倍。 精度使用四舍五偶入奇不入规则。 |
t1 = t2 // i or t1 = t2 // t3 |
计算底数,其余部分(如果有)将被丢弃。在第二种情况下,将返回整数。 (3) |
t1 = t2 % t3 |
余数为一个 timedelta 对象。(3) |
q, r = divmod(t1, t2) |
通过 : q = t1 // t2 (3) and r = t1 % t2 计算出商和余数。q是一个整数,r是一个 timedelta 对象。 |
+t1 |
返回一个相同数值的 timedelta 对象。 |
-t1 |
等价于 timedelta (-t1.days, -t1.seconds, -t1.microseconds), 和 t1 -1. (1)(4) |
abs(t) |
当 t.days >= 0``时等于 +\ t*, 当 ``t.days < 0 时 -t 。 (2) |
str(t) |
返回一个形如 [D day[s], ][H]H:MM:SS[.UUUUUU] 的字符串,当 t 为负数的时候, D 也为负数。 (5) |
repr(t) |
返回一个 timedelta 对象的字符串表示形式,作为附带正规属性值的构造器调用。 |
注释:
结果正确,但可能会溢出。
结果正确,不会溢出。
除以0将会抛出异常
ZeroDivisionError
。-timedelta.max 不是一个
timedelta
类对象。timedelta
对象的字符串表示形式类似于其内部表示形式被规范化。对于负时间增量,这会导致一些不寻常的结果。例如:>>> timedelta(hours=-5) datetime.timedelta(days=-1, seconds=68400) >>>print(_) -1 day,19:00:00
表达式
t2 - t3
通常与t2 + (-t3)
是等价的,除非 t3 等于timedelta.max
; 在这种情况下前者会返回结果,而后者则会溢出。
除了上面列举的操作以外,timedelta
对象还支持与 date
和 datetime
对象进行特定的相加和相减运算(见下文)。
在 3.2 版更改: 现在已支持 timedelta
对象与另一个 timedelta
对象相整除或相除,包括求余运算和 divmod()
函数。 现在也支持 timedelta
对象加上或乘以一个 float
对象。
支持 timedelta
对象之间进行比较,但其中有一些注意事项。
==
或 !=
比较 总是 返回一个 bool
对象,无论被比较的对象是什么类型:
>>>from datetime import timedelta
>>> delta1 = timedelta(seconds=57)
>>> delta2 = timedelta(hours=25, seconds=2)
>>> delta2 != delta1
True
>>> delta2 ==5
False
对于所有其他比较 (例如 <
和 >
),当一个 timedelta
对象与其他类型的对象比较时,将引发 TypeError
:
>>> delta2 > delta1
True
>>> delta2 >5
Traceback(most recent call last):
File"<stdin>", line 1,in<module>
TypeError:'>'not supported between instances of 'datetime.timedelta'and'int'
在布尔运算中,timedelta
对象当且仅当其不等于 timedelta(0)
时则会被视为真值。
实例方法:
timedelta.total_seconds
()
返回时间间隔包含了多少秒。造价于 td / timedelta(seconds=1)
。对于其它单位可以直接使用除法的形式 (例如 td / timedelta(microseconds=1)
)。
需要注意的是,时间间隔较大时,这个方法的结果中的微秒将会失真(大多数平台上大于270年视为一个较大的时间间隔)。
3.2 新版功能.
class:timedelta 用法示例
一个标准化的附加示例:
>>># Components of another_year add up to exactly 365 days
>>>from datetime import timedelta
>>> year = timedelta(days=365)
>>> another_year = timedelta(weeks=40, days=84, hours=23,
... minutes=50, seconds=600)
>>> year == another_year
True
>>> year.total_seconds()
31536000.0
timedelta
算术运算的示例:
>>>from datetime import timedelta
>>> year = timedelta(days=365)
>>> ten_years =10* year
>>> ten_years
datetime.timedelta(days=3650)
>>> ten_years.days // 365
10
>>> nine_years = ten_years - year
>>> nine_years
datetime.timedelta(days=3285)
>>> three_years = nine_years // 3
>>> three_years, three_years.days // 365
(datetime.timedelta(days=1095),3)
date
对象
date
对象代表一个理想化历法中的日期(年、月和日),即当今的格列高利历向前后两个方向无限延伸。
公元 1 年 1 月 1日是第 1 日,公元 1 年 1 月 2 日是第 2 日,依此类推。
classdatetime.date
(year, month, day)
所有参数都是必要的。 参数必须是在下面范围内的整数:
MINYEAR <= year <= MAXYEAR
1 <= month <= 12
1 <= 日期 <= 给定年月对应的天数
如果参数不在这些范围内,则抛出 ValueError
异常。
其它构造器,所有的类方法:
classmethoddate.today
()
返回当前的本地日期。
这等价于 date.fromtimestamp(time.time())
。
classmethoddate.fromtimestamp
(timestamp)
返回对应于 POSIX 时间戳的当地时间,例如 time.time()
返回的就是时间戳。
这可能引发 OverflowError
,如果时间戳数值超出所在平台 C localtime()
函数的支持范围的话,并且会在 localtime()
出错时引发 OSError
。 通常该数值会被限制在 1970 年至 2038 年之间。 请注意在时间戳概念包含闰秒的非 POSIX 系统上,闰秒会被 fromtimestamp()
所忽略。
在 3.3 版更改: 引发 OverflowError
而不是 ValueError
,如果时间戳数值超出所在平台 C localtime()
函数的支持范围的话,并会在 localtime()
出错时引发 OSError
而不是 ValueError
。
classmethoddate.fromordinal
(ordinal)
返回对应于预期格列高利历序号的日期,其中公元 1 年 1 月 1 日的序号为 1。
除非 1 <= ordinal <= date.max.toordinal()
否则会引发 ValueError
。对于任意日期 d,date.fromordinal(d.toordinal()) == d
。
classmethoddate.fromisoformat
(date_string)
返回一个对应于以 YYYY-MM-DD
格式给出的 date_string 的 date
对象:
>>>from datetime import date
>>> date.fromisoformat('2019-12-04')
datetime.date(2019,12,4)
这是 date.isoformat()
的逆操作。 它只支持 YYYY-MM-DD
格式。
3.7 新版功能.
classmethoddate.fromisocalendar
(year, week, day)
返回指定 year, week 和 day 所对应 ISO 历法日期的 date
。 这是函数 date.isocalendar()
的逆操作。
3.8 新版功能.
类属性:
date.min
最小的日期 date(MINYEAR, 1, 1)
。
date.max
最大的日期 ,date(MAXYEAR, 12, 31)
。
date.resolution
两个日期对象的最小间隔,timedelta(days=1)
。
实例属性(只读):
date.year
在 MINYEAR
和 MAXYEAR
之间,包含边界。
date.month
1 至 12(含)
date.day
返回1到指定年月的天数间的数字。
支持的运算:
运算 | 结果: |
---|---|
date2 = date1 + timedelta |
date2 等于从 date1 减去 timedelta.days 天。 (1) |
date2 = date1 - timedelta |
计算 date2 的值使得 date2 + timedelta == date1 。 (2) |
timedelta = date1 - date2 |
(3) |
date1 < date2 |
如果 date1 的时间在 date2 之前则认为 date1 小于 date2 。 (4) |
注释:
- 如果
timedelta.days > 0
则 date2 将在时间线上前进,如果timedelta.days < 0
则将后退。 操作完成后date2 - date1 == timedelta.days
。timedelta.seconds
和timedelta.microseconds
会被忽略。 如果date2.year
将小于MINYEAR
或大于MAXYEAR
则会引发OverflowError
。 timedelta.seconds
和timedelta.microseconds
会被忽略。- 此值完全精确且不会溢出。 操作完成后 timedelta.seconds 和 timedelta.microseconds 均为 0,并且 date2 + timedelta == date1。
- 换句话说,当且仅当
date1.toordinal() < date2.toordinal()
时date1 < date2
。 日期比较会引发TypeError
,如果比较目标不为date
对象的话。 不过也可能会返回NotImplemented
,如果比较目标具有timetuple()
属性的话。 这个钩子给予其他日期对象类型实现混合类型比较的机会。 否则,当date
对象与不同类型的对象比较时将会引发TypeError
,除非是==
或!=
比较。 后两种情况将分别返回False
或True
。
在布尔运算中,所有 date
对象都会被视为真值。
实例方法:
date.replace
(year=self.year, month=self.month, day=self.day)
返回一个具有同样值的日期,除非通过任何关键字参数给出了某些形参的新值。
示例:
>>>from datetime import date
>>> d = date(2002,12,31)
>>> d.replace(day=26)
datetime.date(2002,12,26)
date.timetuple
()
返回一个 time.struct_time
,即 time.localtime()
所返回的类型。
hours, minutes 和 seconds 值均为 0,且 DST 旗标值为 -1。
d.timetuple()
等价于:
time.struct_time((d.year, d.month, d.day,0,0,0, d.weekday(), yday,-1))
其中 yday = d.toordinal() - date(d.year, 1, 1).toordinal() + 1
是当前年份中的日期序号,1 月 1 日的序号为 1
。
date.toordinal
()
返回日期的预期格列高利历序号,其中公元 1 年 1 月 1 日的序号为 1。 对于任意 date
对象 d,date.fromordinal(d.toordinal()) == d
。
date.weekday
()
返回一个整数代表星期几,星期一为0,星期天为6。例如, date(2002, 12, 4).weekday() == 2
,表示的是星期三。
返回一个整数代表星期几,星期一为1,星期天为7。例如:date(2002, 12, 4).isoweekday() == 3
,表示星期三。
date.isocalendar
()
返回一个由三部分组成的 named tuple 对象: year
, week
和 weekday
。
ISO 历法是一种被广泛使用的格列高利历。
ISO 年由 52 或 53 个完整星期构成,每个星期开始于星期一结束于星期日。 一个 ISO 年的第一个星期就是(格列高利)历法的一年中第一个包含星期四的星期。 这被称为 1 号星期,这个星期四所在的 ISO 年与其所在的格列高利年相同。
例如,2004 年的第一天是星期四,因此 ISO 2004 年的第一个星期开始于 2003 年 12 月 29 日星期一,结束于 2004 年 1 月 4 日星期日:
>>>from datetime import date
>>> date(2003,12,29).isocalendar()
datetime.IsoCalendarDate(year=2004, week=1, weekday=1)
>>> date(2004,1,4).isocalendar()
datetime.IsoCalendarDate(year=2004, week=1, weekday=7)
在 3.9 版更改: 结果由元组改为 named tuple。
date.isoformat
()
返回一个以 ISO 8601 格式 YYYY-MM-DD
来表示日期的字符串:
>>>from datetime import date
>>> date(2002,12,4).isoformat()
'2002-12-04'
这是 date.fromisoformat()
的逆操作。
date.__str__
()
对于日期对象 d, str(d)
等价于 d.isoformat()
。
date.ctime
()
返回一个表示日期的字符串:
>>>from datetime import date
>>> date(2002,12,4).ctime()
'Wed Dec 4 00:00:00 2002'
d.ctime()
等效于:
time.ctime(time.mktime(d.timetuple()))
在原生 C ctime()
函数 (time.ctime()
会发起调用该函数,但 date.ctime()
则不会) 遵循 C 标准的平台上。
date.strftime
(format)
返回一个由显式格式字符串所指明的代表日期的字符串。 表示时、分或秒的格式代码值将为 0。
date.__format__
(format)
与 date.strftime()
相同。 此方法使得为 date
对象指定以 格式化字符串字面值 表示的格式化字符串以及使用 str.format()
进行格式化成为可能。
class:date 用法示例
计算距离特定事件天数的例子:
>>>import time
>>>from datetime import date
>>> today = date.today()
>>> today
datetime.date(2007,12,5)
>>> today == date.fromtimestamp(time.time())
True
>>> my_birthday = date(today.year,6,24)
>>>if my_birthday < today:
... my_birthday = my_birthday.replace(year=today.year +1)
>>> my_birthday
datetime.date(2008,6,24)
>>> time_to_birthday = abs(my_birthday - today)
>>> time_to_birthday.days
202
使用 date
的更多例子:
>>>from datetime import date
>>> d = date.fromordinal(730920)# 730920th day after 1. 1. 0001
>>> d
datetime.date(2002,3,11)
>>># Methods related to formatting string output
>>> d.isoformat()
'2002-03-11'
>>> d.strftime("%d/%m/%y")
'11/03/02'
>>> d.strftime("%A %d. %B %Y")
'Monday 11. March 2002'
>>> d.ctime()
'Mon Mar 11 00:00:00 2002'
>>>'The {1} is {0:%d}, the {2} is {0:%B}.'.format(d,"day","month")
'The day is 11, the month is March.'
>>># Methods for to extracting 'components' under different calendars
>>> t = d.timetuple()
>>>for i in t:
...print(i)
2002# year
3# month
11# day
0
0
0
0# weekday (0 = Monday)
70# 70th day in the year
-1
>>> ic = d.isocalendar()
>>>for i in ic:
...print(i)
2002# ISO year
11# ISO week number
1# ISO day number ( 1 = Monday )
>>># A date object is immutable; all operations produce a new object
>>> d.replace(year=2005)
datetime.date(2005,3,11)
datetime
对象
datetime
对象是包含来自 date
对象和 time
对象的所有信息的单一对象。
与 date
对象一样,datetime
假定当前的格列高利历向前后两个方向无限延伸;与 time
对象一样,datetime
假定每一天恰好有 3600*24 秒。
构造器 :
classdatetime.datetime
(year, month, day, hour=0, minute=0, second=0, microsecond=0, tzinfo=None, **, fold=0*)
year, month 和 day 参数是必须的。 tzinfo 可以是 None
或者是一个 tzinfo
子类的实例。 其余的参数必须是在下面范围内的整数:
MINYEAR <= year <= MAXYEAR
,1 <= month <= 12
,1 <= day <= 指定年月的天数
,0 <= hour < 24
,0 <= minute < 60
,0 <= second < 60
,0 <= microsecond < 1000000
,fold in [0, 1]
.
如果参数不在这些范围内,则抛出 ValueError
异常。
3.6 新版功能: 增加了 fold
参数。
其它构造器,所有的类方法:
classmethoddatetime.today
()
返回表示当前地方时的 datetime 对象,其中 tzinfo
为 None
。
等价于:
datetime.fromtimestamp(time.time())
此方法的功能等价于 now()
,但是不带 tz
形参。
classmethoddatetime.now
(tz=None)
返回表示当前地方时的 date 和 time 对象。
如果可选参数 tz 为 None
或未指定,这就类似于 today()
,但该方法会在可能的情况下提供比通过 time.time()
时间戳所获时间值更高的精度(例如,在提供了 C gettimeofday()
函数的平台上就可以做到这一点)。
如果 tz 不为 None
,它必须是 tzinfo
子类的一个实例,并且当前日期和时间将被转换到 tz 时区。
此函数可以替代 today()
和 utcnow()
。
classmethoddatetime.utcnow
()
返回表示当前 UTC 时间的 date 和 time,其中 tzinfo
为 None
。
这类似于 now()
,但返回的是当前 UTC 日期和时间,类型为简单型 datetime
对象。 感知型的当前 UTC 日期时间可通过调用 datetime.now(timezone.utc)
来获得。
警告
由于简单型 datetime
对象会被许多 datetime
方法当作本地时间来处理,最好是使用感知型日期时间对象来表示 UTC 时间。 因此,创建表示当前 UTC 时间的对象的推荐方式是通过调用 datetime.now(timezone.utc)
。
classmethoddatetime.fromtimestamp
(timestamp, tz=None)
返回对应于 POSIX 时间戳例如 time.time()
的返回值的本地日期和时间。 如果可选参数 tz 为 None
或未指定,时间戳会被转换为所在平台的本地日期和时间,返回的 datetime
对象将为天真型。
如果 tz 不为 None
,它必须是 tzinfo
子类的一个实例,并且时间戳将被转换到 tz 指定的时区。
fromtimestamp()
可能会引发 OverflowError
,如果时间戳数值超出所在平台 C localtime()
或 gmtime()
函数的支持范围的话,并会在 localtime()
或 gmtime()
报错时引发 OSError
。 通常该数值会被限制在 1970 年至 2038 年之间。 请注意在时间戳概念包含闰秒的非 POSIX 系统上,闰秒会被 fromtimestamp()
所忽略,结果可能导致两个相差一秒的时间戳产生相同的 datetime
对象。 相比 utcfromtimestamp()
更推荐使用此方法。
在 3.3 版更改: 引发 OverflowError
而不是 ValueError
,如果时间戳数值超出所在平台 C localtime()
或 gmtime()
函数的支持范围的话。 并会在 localtime()
或 gmtime()
出错时引发 OSError
而不是 ValueError
。
在 3.6 版更改: fromtimestamp()
可能返回 fold
值设为 1 的实例。
classmethoddatetime.utcfromtimestamp
(timestamp)
返回对应于 POSIX 时间戳的 UTC datetime
,其中 tzinfo
值为 None
。 (结果为简单型对象。)
这可能引发 OverflowError
,如果时间戳数值超出所在平台 C gmtime()
函数的支持范围的话,并会在 gmtime()
报错时引发 OSError
。 通常该数值会被限制在 1970 至 2038 年之间。
要得到一个感知型 datetime
对象,应调用 fromtimestamp()
:
datetime.fromtimestamp(timestamp, timezone.utc)
在 POSIX 兼容的平台上,它等价于以下表达式:
datetime(1970,1,1, tzinfo=timezone.utc)+ timedelta(seconds=timestamp)
不同之处在于后一种形式总是支持完整年份范围:从 MINYEAR
到 MAXYEAR
的开区间。
警告
由于简单型 datetime
对象会被许多 datetime
方法当作本地时间来处理,最好是使用感知型日期时间对象来表示 UTC 时间。 因此,创建表示特定 UTC 时间戳的日期时间对象的推荐方式是通过调用 datetime.fromtimestamp(timestamp, tz=timezone.utc)
。
在 3.3 版更改: 引发 OverflowError
而不是 ValueError
,如果时间戳数值超出所在平台 C gmtime()
函数的支持范围的话。 并会在 gmtime()
出错时引发 OSError
而不是 ValueError
。
classmethoddatetime.fromordinal
(ordinal)
返回对应于预期格列高利历序号的 datetime
,其中公元 1 年 1 月 1 日的序号为 1。 除非 1 <= ordinal <= datetime.max.toordinal()
否则会引发 ValueError
。 结果的 hour, minute, second 和 microsecond 值均为 0,并且 tzinfo
值为 None
。
classmethoddatetime.combine
(date, time, tzinfo=self.tzinfo)
返回一个新的 datetime
对象,对象的日期部分等于给定的 date
对象的值,而其时间部分等于给定的 time
对象的值。 如果提供了 tzinfo 参数,其值会被用来设置结果的 tzinfo
属性,否则将使用 time 参数的 tzinfo
属性。
对于任意 datetime
对象 d,d == datetime.combine(d.date(), d.time(), d.tzinfo)
。 如果 date 是一个 datetime
对象,它的时间部分和 tzinfo
属性会被忽略。
在 3.6 版更改: 增加了 tzinfo 参数。
classmethoddatetime.fromisoformat
(date_string)
返回一个对应于 date.isoformat()
和 datetime.isoformat()
所提供的某一种 date_string 的 datetime
对象。
特别地,此函数支持以下格式的字符串:
YYYY-MM-DD[*HH[:MM[:SS[.fff[fff]]]][+HH:MM[:SS[.ffffff]]]]
其中 *
可以匹配任意的单个字符。
警告
此函数 并不 支持解析任意 ISO 8601 字符串 —— 它的目的只是作为 datetime.isoformat()
的逆操作。 在第三方包 dateutil 中提供了一个更完善的 ISO 8601 解析器 dateutil.parser.isoparse
。
示例:
>>>from datetime import datetime
>>> datetime.fromisoformat('2011-11-04')
datetime.datetime(2011,11,4,0,0)
>>> datetime.fromisoformat('2011-11-04T00:05:23')
datetime.datetime(2011,11,4,0,5,23)
>>> datetime.fromisoformat('2011-11-04 00:05:23.283')
datetime.datetime(2011,11,4,0,5,23,283000)
>>> datetime.fromisoformat('2011-11-04 00:05:23.283+00:00')
datetime.datetime(2011,11,4,0,5,23,283000, tzinfo=datetime.timezone.utc)
>>> datetime.fromisoformat('2011-11-04T00:05:23+04:00')
datetime.datetime(2011,11,4,0,5,23,
tzinfo=datetime.timezone(datetime.timedelta(seconds=14400)))
3.7 新版功能.
classmethoddatetime.fromisocalendar
(year, week, day)
返回以 year, week 和 day 值指明的 ISO 历法日期所对应的 datetime
。 该datetime 对象的非日期部分将使用其标准默认值来填充。 这是函数 datetime.isocalendar()
的逆操作。
3.8 新版功能.
classmethoddatetime.strptime
(date_string, format)
返回一个对应于 date_string*,根据 *format 进行解析得到的 datetime
对象。
这相当于:
datetime(*(time.strptime(date_string, format)[0:6]))
如果 date_string 和 format 无法被 time.strptime()
解析或它返回一个不是时间元组的值,则将引发 ValueError
。
类属性:
datetime.min
最早的可表示 datetime
,datetime(MINYEAR, 1, 1, tzinfo=None)
。
datetime.max
最晚的可表示 datetime
,datetime(MAXYEAR, 12, 31, 23, 59, 59, 999999, tzinfo=None)
。
datetime.resolution
两个不相等的 datetime
对象之间可能的最小间隔,timedelta(microseconds=1)
。
实例属性(只读):
datetime.year
在 MINYEAR
和 MAXYEAR
之间,包含边界。
datetime.month
1 至 12(含)
datetime.day
返回1到指定年月的天数间的数字。
datetime.hour
取值范围是 range(24)
。
datetime.minute
取值范围是 range(60)
。
datetime.second
取值范围是 range(60)
。
datetime.microse