Python 2.4 新特性¶
- 作者:
A.M. Kuchling
本文介绍了 2005 年 3 月 30 日发布的 Python 2.4.1 中的新功能。
Python 2.4 是一个中等规模的版本。它不像激进的 Python 2.2 那样引入了许多更改,但引入的功能比保守的 2.3 版本多。 最重要的新语言特性是函数装饰器和生成器表达式; 大多数其他更改都针对标准库。
根据 CVS 更改日志,在 Python 2.3 和 2.4 之间应用了 481 个补丁,修复了 502 个错误。这两个数字都可能被低估了。
本文不试图提供每个新功能的完整规范,而是提供每个功能的简要介绍。 有关完整详细信息,您应参考 Python 2.4 的文档,例如 Python 库参考和 Python 参考手册。 通常,您将被推荐使用特定新功能的 PEP,以了解实现和设计原理。
PEP 218:内置集合对象¶
Python 2.3 引入了 sets
模块。现在,集合数据类型的 C 实现已作为两个新的内置类型 set(iterable)
和 frozenset(iterable)
添加到 Python 核心中。它们为成员资格测试、从序列中消除重复项以及诸如并集、交集、差集和对称差集之类的数学运算提供了高速操作。
>>> a = set('abracadabra') # form a set from a string
>>> 'z' in a # fast membership testing
False
>>> a # unique letters in a
set(['a', 'r', 'b', 'c', 'd'])
>>> ''.join(a) # convert back into a string
'arbcd'
>>> b = set('alacazam') # form a second set
>>> a - b # letters in a but not in b
set(['r', 'd', 'b'])
>>> a | b # letters in either a or b
set(['a', 'c', 'r', 'd', 'b', 'm', 'z', 'l'])
>>> a & b # letters in both a and b
set(['a', 'c'])
>>> a ^ b # letters in a or b but not both
set(['r', 'd', 'b', 'm', 'z', 'l'])
>>> a.add('z') # add a new element
>>> a.update('wxy') # add multiple new elements
>>> a
set(['a', 'c', 'b', 'd', 'r', 'w', 'y', 'x', 'z'])
>>> a.remove('x') # take one element out
>>> a
set(['a', 'c', 'b', 'd', 'r', 'w', 'y', 'z'])
frozenset()
类型是 set()
的不可变版本。 由于它是不可变的并且可哈希的,因此可以用作字典键或另一个集合的成员。
sets
模块保留在标准库中,如果您希望子类化 Set
或 ImmutableSet
类,它可能会很有用。目前没有计划弃用该模块。
另请参阅
- PEP 218 - 添加内置集合对象类型
最初由 Greg Wilson 提出,最终由 Raymond Hettinger 实现。
PEP 237:统一长整数和整数¶
此 PEP 的漫长过渡过程始于 Python 2.2,在 Python 2.4 中又向前迈进了一步。 在 2.3 中,某些在 int/long 统一后行为不同的整数运算会触发 FutureWarning
警告,并返回限制为 32 位或 64 位(取决于您的平台)的值。在 2.4 中,这些表达式不再产生警告,而是产生不同的结果,通常是长整数。
有问题的表达式主要是左移和冗长的十六进制和八进制常量。 例如,2 << 32
在 2.3 中会产生警告,在 32 位平台上计算结果为 0。在 Python 2.4 中,此表达式现在返回正确答案 8589934592。
另请参阅
- PEP 237 - 统一长整数和整数
原始 PEP 由 Moshe Zadka 和 GvR 编写。 2.4 的更改由 Kalle Svensson 实现。
PEP 289:生成器表达式¶
Python 2.2 中引入的迭代器特性和 itertools
模块使编写循环遍历大型数据集的程序更容易,而无需一次将整个数据集保存在内存中。 列表推导式不太适合这种情况,因为它们会生成一个包含所有项的 Python 列表对象。 这不可避免地会将所有对象拉入内存,如果您的数据集非常大,这可能会成为问题。 在尝试编写函数式风格的程序时,很自然地会写成类似于
links = [link for link in get_all_links() if not link.followed]
for link in links:
...
而不是
for link in get_all_links():
if link.followed:
continue
...
第一种形式更简洁,可能更具可读性,但如果您正在处理大量链接对象,则必须编写第二种形式,以避免同时将所有链接对象都保存在内存中。
生成器表达式的工作方式与列表推导式类似,但不会物化整个列表; 相反,它们会创建一个生成器,该生成器将逐个返回元素。 上面的例子可以写成
links = (link for link in get_all_links() if not link.followed)
for link in links:
...
生成器表达式始终必须写在括号内,如上面的示例所示。 表示函数调用的括号也计算在内,因此如果要创建一个将立即传递给函数的迭代器,则可以写成
print sum(obj.count for obj in list_all_objects())
生成器表达式在各种小方面与列表推导式不同。 最值得注意的是,循环变量(在上面的示例中为obj)在生成器表达式之外是不可访问的。 列表推导式将变量赋值给其最后的值; Python 的未来版本将更改此设置,使列表推导式在这方面与生成器表达式匹配。
另请参阅
- PEP 289 - 生成器表达式
由 Raymond Hettinger 提出,由 Jiwon Seo 实现,早期工作由 Hye-Shik Chang 指导。
PEP 292:更简单的字符串替换¶
标准库中的一些新类为将变量替换到字符串中提供了另一种机制; 这种替换样式可能更适合未经培训的用户需要编辑模板的应用程序。
按名称替换变量的常用方法是 %
运算符
>>> '%(page)i: %(title)s' % {'page':2, 'title': 'The Best of Times'}
'2: The Best of Times'
在编写模板字符串时,很容易忘记右括号后面的 i
或 s
。 如果模板在 Python 模块中,这不是一个大问题,因为您运行代码,会得到“不支持的格式字符” ValueError
并修复问题。 但是,考虑一下诸如 Mailman 之类的应用程序,其中模板字符串或翻译由不了解 Python 语言的用户编辑。 格式字符串的语法对于此类用户来说很难解释,如果他们犯了错误,则很难向他们提供有用的反馈。
PEP 292 将 Template
类添加到 string
模块,该模块使用 $
来指示替换
>>> import string
>>> t = string.Template('$page: $title')
>>> t.substitute({'page':2, 'title': 'The Best of Times'})
'2: The Best of Times'
如果字典中缺少键,则 substitute()
方法将引发 KeyError
。 还有一个 safe_substitute()
方法会忽略缺少的键
>>> t = string.Template('$page: $title')
>>> t.safe_substitute({'page':3})
'3: $title'
另请参阅
- PEP 292 - 更简单的字符串替换
由 Barry Warsaw 编写和实现。
PEP 318:函数和方法的装饰器¶
Python 2.2 通过添加静态方法和类方法扩展了 Python 的对象模型,但它没有扩展 Python 的语法来提供定义静态方法或类方法的任何新方法。 相反,您必须以通常的方式编写 def
语句,并将结果方法传递给 staticmethod()
或 classmethod()
函数,该函数会将该函数包装为新类型的方法。 您的代码如下所示
class C:
def meth (cls):
...
meth = classmethod(meth) # Rebind name to wrapped-up class method
如果方法很长,就很容易错过或忘记函数体后面的 classmethod()
调用。
最初的想法是添加一些语法来使此类定义更具可读性,但在 2.2 版本发布时,一个好的语法并不明显。如今,一个好的语法仍然不明显,但用户要求更容易访问该功能;因此添加了一个新的语法特性来满足这一需求。
这个新特性被称为“函数装饰器”。这个名称源于这样一个想法:classmethod()
、staticmethod()
和类似的功能正在函数对象上存储额外的信息;它们正在用更多细节装饰函数。
这个符号借鉴了 Java,并使用 '@'
字符作为指示符。使用新的语法,上面的示例将写成
class C:
@classmethod
def meth (cls):
...
@classmethod
是 meth=classmethod(meth)
赋值的简写形式。更一般地说,如果您有以下代码
@A
@B
@C
def f ():
...
它等效于以下预装饰器代码
def f(): ...
f = A(B(C(f)))
装饰器必须在函数定义之前的行上出现,每行一个装饰器,并且不能与 def 语句在同一行,这意味着 @A def f(): ...
是非法的。您只能装饰函数定义,无论是在模块级别还是在类内部;您不能装饰类定义。
装饰器只是一个函数,它将要装饰的函数作为参数,并返回相同的函数或一些新对象。除非将其他装饰器应用于结果,否则装饰器的返回值不必是可调用的(尽管通常是这样)。编写自己的装饰器很容易。以下简单示例仅在函数对象上设置一个属性
>>> def deco(func):
... func.attr = 'decorated'
... return func
...
>>> @deco
... def f(): pass
...
>>> f
<function f at 0x402ef0d4>
>>> f.attr
'decorated'
>>>
作为一个稍微更实际的示例,以下装饰器检查提供的参数是否为整数
def require_int (func):
def wrapper (arg):
assert isinstance(arg, int)
return func(arg)
return wrapper
@require_int
def p1 (arg):
print arg
@require_int
def p2(arg):
print arg*2
在 PEP 318 中的一个示例包含了一个更花哨的这个想法的版本,它可以让您指定所需的类型并检查返回的类型。
装饰器函数可以接受参数。如果提供了参数,则会使用这些参数调用您的装饰器函数,并且必须返回一个新的装饰器函数;此函数必须接受一个函数并返回一个函数,如前所述。换句话说,@A @B @C(args)
变为
def f(): ...
_deco = C(args)
f = A(B(_deco(f)))
正确理解这一点可能有点绕弯,但并不太难。
一个小的相关更改使得函数的 func_name
属性可写。此属性用于在回溯中显示函数名称,因此装饰器应更改任何已构造并返回的新函数的名称。
另请参阅
- PEP 318 - 函数、方法和类的装饰器
由 Kevin D. Smith、Jim Jewett 和 Skip Montanaro 编写。有几个人编写了实现函数装饰器的补丁,但实际签入的补丁是 Mark Russell 编写的补丁 #979728。
- https://wiki.python.org/moin/PythonDecoratorLibrary
此 Wiki 页面包含几个装饰器的示例。
PEP 322:反向迭代¶
一个新的内置函数 reversed(seq)
接受一个序列,并返回一个以相反顺序循环遍历序列元素的迭代器。
>>> for i in reversed(xrange(1,4)):
... print i
...
3
2
1
与扩展切片(例如 range(1,4)[::-1]
)相比,reversed()
更易于阅读,运行速度更快,并且使用的内存少得多。
请注意,reversed()
仅接受序列,不接受任意迭代器。如果要反转迭代器,请先使用 list()
将其转换为列表。
>>> input = open('/etc/passwd', 'r')
>>> for line in reversed(list(input)):
... print line
...
root:*:0:0:System Administrator:/var/root:/bin/tcsh
...
另请参阅
- PEP 322 - 反向迭代
由 Raymond Hettinger 编写和实现。
PEP 324:新的子进程模块¶
标准库提供了许多执行子进程的方法,它们提供了不同的功能和不同的复杂程度。os.system(command)
易于使用,但速度较慢(它运行一个执行命令的 shell 进程)且危险(您必须小心转义 shell 的元字符)。popen2
模块提供了可以捕获子进程的标准输出和标准错误输出的类,但命名令人困惑。subprocess
模块清理了这一点,提供了一个统一的接口,可以满足您可能需要的所有功能。
与 popen2
的类集合不同,subprocess
包含一个名为 subprocess.Popen
的类,其构造函数支持许多不同的关键字参数。
class Popen(args, bufsize=0, executable=None,
stdin=None, stdout=None, stderr=None,
preexec_fn=None, close_fds=False, shell=False,
cwd=None, env=None, universal_newlines=False,
startupinfo=None, creationflags=0):
args 通常是一个字符串序列,它将作为子进程执行的程序的参数。(如果 shell 参数为 true,则 args 可以是一个字符串,然后将该字符串传递给 shell 进行解释,就像 os.system()
所做的那样。)
stdin、stdout 和 stderr 指定子进程的输入、输出和错误流将是什么。您可以提供文件对象或文件描述符,也可以使用常量 subprocess.PIPE
在子进程和父进程之间创建管道。
构造函数有许多方便的选项
close_fds 请求在运行子进程之前关闭所有文件描述符。
cwd 指定将在其中执行子进程的工作目录(默认为父进程的工作目录)。
env 是一个指定环境变量的字典。
preexec_fn 是一个在启动子进程之前调用的函数。
universal_newlines 使用 Python 的 通用换行符 功能打开子进程的输入和输出。
创建 Popen
实例后,您可以调用其 wait()
方法来暂停直到子进程退出,调用 poll()
来检查它是否已退出而不会暂停,或者调用 communicate(data)
将字符串 data 发送到子进程的标准输入。communicate(data)
然后读取子进程发送到其标准输出或标准错误的任何数据,返回一个元组 (stdout_data, stderr_data)
。
call()
是一个快捷方式,它将其参数传递给 Popen
构造函数,等待命令完成,并返回子进程的状态码。它可以作为 os.system()
的更安全替代方案
sts = subprocess.call(['dpkg', '-i', '/tmp/new-package.deb'])
if sts == 0:
# Success
...
else:
# dpkg returned an error
...
该命令的调用不使用 shell。如果您确实想使用 shell,您可以添加 shell=True
作为关键字参数,并提供一个字符串而不是一个序列
sts = subprocess.call('dpkg -i /tmp/new-package.deb', shell=True)
该 PEP 采用了 shell 和 Python 代码的各种示例,并展示了如何将它们转换为使用 subprocess
的 Python 代码。强烈建议阅读 PEP 的这一部分。
另请参阅
- PEP 324 - subprocess - 新进程模块
由 Peter Åstrand 编写和实现,并得到 Fredrik Lundh 和其他人的协助。
PEP 327:十进制数据类型¶
Python 一直支持浮点 (FP) 数字,它基于底层的 C double 类型,作为一种数据类型。然而,尽管大多数编程语言都提供了浮点类型,但许多人(甚至程序员)都没有意识到浮点数不能准确地表示某些十进制小数。新的 Decimal
类型可以准确地表示这些小数,直到用户指定的精度限制。
为什么需要 Decimal?¶
局限性源于用于浮点数的表示形式。FP 数字由三个分量组成
符号,即正数或负数。
尾数,这是一个由一位二进制数后跟一个小数部分组成的数。例如,以 2 为底的表示法中的
1.01
在十进制表示法中是1 + 0/2 + 1/4
,或 1.25。指数,它指示所表示的数字中小数点的位置。
例如,数字 1.25 具有正号、尾数值为 1.01(以二进制表示)和指数 0(不需要移动小数点)。数字 5 具有相同的符号和尾数,但指数为 2,因为尾数乘以 4(2 的指数 2 次幂);1.25 * 4 等于 5。
现代系统通常提供符合 IEEE 754 标准的浮点支持。C 语言的 double 类型通常被实现为 64 位 IEEE 754 数字,它使用 52 位空间来表示尾数。这意味着数字只能精确到 52 位。如果要表示的数字展开后会无限重复,那么这个展开会在 52 位后被截断。不幸的是,大多数软件需要以 10 为底输出,而以 10 为底的常用分数在二进制中通常是无限循环小数。例如,十进制的 1.1 在二进制中是 1.0001100110011 ...
;.1 = 1/16 + 1/32 + 1/256 加上无限多的附加项。IEEE 754 必须在 52 位后截断这个无限重复的小数,因此表示会略有不准确。
有时,当打印数字时,您可以看到这种不准确性。
>>> 1.1
1.1000000000000001
当您打印数字时,这种不准确性并不总是可见的,因为 FP 到十进制字符串的转换是由 C 库提供的,并且大多数 C 库都试图产生合理的输出。然而,即使它没有显示出来,这种不准确性仍然存在,并且后续操作可能会放大错误。
对于许多应用程序来说,这并不重要。如果我正在绘制点并在我的显示器上显示它们,那么 1.1 和 1.1000000000000001 之间的差异太小,无法被看到。报告通常将输出限制为特定的小数位数,如果您将数字四舍五入到两位、三位甚至八位小数,则永远不会出现错误。但是,对于确实重要的应用程序来说,实现您自己的自定义算术例程需要做很多工作。
因此,创建了 Decimal
类型。
Decimal
类型¶
一个新的模块 decimal
被添加到 Python 的标准库中。它包含两个类,Decimal
和 Context
。Decimal
实例表示数字,Context
实例用于封装各种设置,例如精度和默认舍入模式。
Decimal
实例是不可变的,就像常规的 Python 整数和 FP 数字一样;一旦创建,您就无法更改实例表示的值。Decimal
实例可以从整数或字符串创建。
>>> import decimal
>>> decimal.Decimal(1972)
Decimal("1972")
>>> decimal.Decimal("1.1")
Decimal("1.1")
您还可以提供包含符号、以十进制数字元组表示的尾数和指数的元组。
>>> decimal.Decimal((1, (1, 4, 7, 5), -2))
Decimal("-14.75")
注意:符号位是一个布尔值,因此 0 为正,1 为负。
从浮点数转换会带来一点问题:表示 1.1 的 FP 数字应该转换为完全是 1.1 的十进制数,还是转换为 1.1 加上任何引入的不准确之处? 决定是回避这个问题,并将这种转换排除在 API 之外。相反,您应该使用所需的精度将浮点数转换为字符串,并将该字符串传递给 Decimal
构造函数。
>>> f = 1.1
>>> decimal.Decimal(str(f))
Decimal("1.1")
>>> decimal.Decimal('%.12f' % f)
Decimal("1.100000000000")
一旦您拥有 Decimal
实例,您就可以对它们执行通常的数学运算。一个限制:求幂需要整数指数。
>>> a = decimal.Decimal('35.72')
>>> b = decimal.Decimal('1.73')
>>> a+b
Decimal("37.45")
>>> a-b
Decimal("33.99")
>>> a*b
Decimal("61.7956")
>>> a/b
Decimal("20.64739884393063583815028902")
>>> a ** 2
Decimal("1275.9184")
>>> a**b
Traceback (most recent call last):
...
decimal.InvalidOperation: x ** (non-integer)
您可以将 Decimal
实例与整数组合,但不能与浮点数组合。
>>> a + 4
Decimal("39.72")
>>> a + 4.5
Traceback (most recent call last):
...
TypeError: You can interact Decimal only with int, long or Decimal data types.
>>>
Decimal
数字可以与 math
和 cmath
模块一起使用,但请注意,在执行操作之前,它们将立即转换为浮点数,从而可能导致精度和准确性的损失。您还将得到一个常规的浮点数而不是 Decimal
。
>>> import math, cmath
>>> d = decimal.Decimal('123456789012.345')
>>> math.sqrt(d)
351364.18288201344
>>> cmath.sqrt(-d)
351364.18288201344j
Decimal
实例有一个 sqrt()
方法,该方法返回一个 Decimal
,但如果您需要其他函数,例如三角函数,则必须自己实现它们。
>>> d.sqrt()
Decimal("351364.1828820134592177245001")
Context
类型¶
Context
类的实例封装了十进制运算的几个设置。
prec
是精度,即小数位数。rounding
指定舍入模式。decimal
模块具有各种可能性的常量:ROUND_DOWN
、ROUND_CEILING
、ROUND_HALF_EVEN
以及其他各种常量。traps
是一个字典,用于指定在遇到某些错误条件时会发生什么:要么引发异常,要么返回一个值。错误条件的一些示例包括除以零、精度损失和溢出。
通过调用 getcontext()
可以获得一个线程本地的默认上下文;您可以更改此上下文的属性以更改默认精度、舍入或陷阱处理。以下示例显示了更改默认上下文的精度的效果。
>>> decimal.getcontext().prec
28
>>> decimal.Decimal(1) / decimal.Decimal(7)
Decimal("0.1428571428571428571428571429")
>>> decimal.getcontext().prec = 9
>>> decimal.Decimal(1) / decimal.Decimal(7)
Decimal("0.142857143")
错误条件的默认操作是可选的;该模块可以返回一个特殊值,例如无穷大或非数字,或者可以引发异常。
>>> decimal.Decimal(1) / decimal.Decimal(0)
Traceback (most recent call last):
...
decimal.DivisionByZero: x / 0
>>> decimal.getcontext().traps[decimal.DivisionByZero] = False
>>> decimal.Decimal(1) / decimal.Decimal(0)
Decimal("Infinity")
>>>
Context
实例还有各种格式化数字的方法,例如 to_eng_string()
和 to_sci_string()
。
有关更多信息,请参阅 decimal
模块的文档,其中包括一个快速入门教程和参考。
另请参阅
- PEP 327 - 十进制数据类型
由 Facundo Batista 编写,并由 Facundo Batista、Eric Price、Raymond Hettinger、Aahz 和 Tim Peters 实现。
- http://www.lahey.com/float.htm
本文使用 Fortran 代码来说明浮点数不准确可能导致的许多问题。
- https://speleotrove.com/decimal/
基于十进制的表示的描述。这种表示形式正在被提议作为标准,并且是新的 Python 十进制类型的基础。此材料的大部分由 Rexx 语言的设计者 Mike Cowlishaw 编写。
PEP 328:多行导入¶
一项语言更改是对语法的微小调整,旨在使从模块导入许多名称变得更容易。在 from module import names
语句中,names 是一个以逗号分隔的名称序列。如果序列很长,您可以从同一个模块编写多个导入,或者可以使用反斜杠转义行尾,如下所示:
from SimpleXMLRPCServer import SimpleXMLRPCServer,\
SimpleXMLRPCRequestHandler,\
CGIXMLRPCRequestHandler,\
resolve_dotted_attribute
Python 2.4 中的语法更改只是允许将名称放在括号内。Python 会忽略带括号的表达式中的换行符,因此不再需要反斜杠。
from SimpleXMLRPCServer import (SimpleXMLRPCServer,
SimpleXMLRPCRequestHandler,
CGIXMLRPCRequestHandler,
resolve_dotted_attribute)
PEP 还建议所有 import
语句都是绝对导入,使用前导 .
字符来指示相对导入。PEP 的这部分未在 Python 2.4 中实现,但在 Python 2.5 中完成。
另请参阅
- PEP 328 - 导入:多行和绝对/相对
由 Aahz 编写。多行导入由 Dima Dorfman 实现。
PEP 331:与区域设置无关的浮点/字符串转换¶
locale
模块允许 Python 软件选择各种转换和显示约定,这些转换和显示约定本地化为特定的国家或语言。但是,该模块小心地不更改数字区域设置,因为 Python 实现中的各种函数要求将数字区域设置保持设置为 'C'
区域设置。通常这是因为代码正在使用 C 库的 atof()
函数。
但是,不设置数字区域设置给使用第三方 C 库的扩展带来了麻烦,因为它们没有设置正确的区域设置。 激励示例是 GTK+,其用户界面小部件没有以当前区域设置显示数字。
PEP 中描述的解决方案是在 Python API 中添加三个新函数,它们执行仅限 ASCII 的转换,忽略区域设置。
PyOS_ascii_strtod(str, ptr)
和PyOS_ascii_atof(str, ptr)
都将字符串转换为 C double。PyOS_ascii_formatd(buffer, buf_len, format, d)
将 double 转换为 ASCII 字符串。
这些函数的代码来自 GLib 库 (https://developer-old.gnome.org/glib/2.26/),其开发人员慷慨地重新许可了相关函数并将其捐赠给了 Python 软件基金会。locale
模块现在可以更改数字区域设置,从而使 GTK+ 等扩展产生正确的结果。
另请参阅
- PEP 331 - 与区域设置无关的浮点/字符串转换
由 Christian R. Reis 编写,并由 Gustavo Carneiro 实现。
其他语言更改¶
以下是 Python 2.4 对核心 Python 语言所做的所有更改。
为函数和方法添加了装饰器 (PEP 318)。
增加了内置的
set()
和frozenset()
类型 (PEP 218)。其他新的内置函数包括reversed(seq)
函数 (PEP 322)。增加了生成器表达式 (PEP 289)。
某些数值表达式不再返回限制为 32 位或 64 位的值 (PEP 237)。
现在可以在
from module import names
语句中用括号括起名称列表 (PEP 328)。dict.update()
方法现在接受与dict
构造函数相同的参数形式。这包括任何映射、任何键/值对的可迭代对象以及关键字参数。(由 Raymond Hettinger 贡献。)字符串方法
ljust()
、rjust()
和center()
现在接受一个可选参数来指定除空格以外的填充字符。(由 Raymond Hettinger 贡献。)字符串还获得了一个
rsplit()
方法,该方法的工作方式类似于split()
方法,但从字符串末尾开始拆分。(由 Sean Reifschneider 贡献。)>>> 'www.python.org'.split('.', 1) ['www', 'python.org'] 'www.python.org'.rsplit('.', 1) ['www.python', 'org']
在列表的
sort()
方法中添加了三个关键字参数,cmp、key 和 reverse。这些参数使sort()
的一些常见用法更加简单。所有这些参数都是可选的。对于 cmp 参数,该值应该是一个比较函数,它接受两个参数,并根据参数的比较方式返回 -1、0 或 +1。然后,此函数将用于对列表进行排序。以前,这是可以提供给
sort()
的唯一参数。key 应该是一个单参数函数,它接受一个列表元素并返回该元素的比较键。然后使用比较键对列表进行排序。以下示例不区分大小写地对列表进行排序
>>> L = ['A', 'b', 'c', 'D'] >>> L.sort() # Case-sensitive sort >>> L ['A', 'D', 'b', 'c'] >>> # Using 'key' parameter to sort list >>> L.sort(key=lambda x: x.lower()) >>> L ['A', 'b', 'c', 'D'] >>> # Old-fashioned way >>> L.sort(cmp=lambda x,y: cmp(x.lower(), y.lower())) >>> L ['A', 'b', 'c', 'D']
最后一个示例使用 cmp 参数,这是执行不区分大小写排序的旧方法。它可以工作,但比使用 key 参数慢。使用 key 为列表中的每个元素调用一次
lower()
方法,而使用 cmp 将为每个比较调用两次,因此使用 key 可以节省lower()
方法的调用次数。对于简单的键函数和比较函数,通常可以通过使用未绑定的方法来避免
lambda
表达式。例如,上面的不区分大小写的排序最好写成>>> L.sort(key=str.lower) >>> L ['A', 'b', 'c', 'D']
最后,reverse 参数接受一个布尔值。如果该值为 true,则列表将按相反顺序排序。现在可以编写
L.sort(reverse=True)
,而不是L.sort(); L.reverse()
。现在保证排序的结果是稳定的。这意味着具有相同键的两个条目将以与输入时相同的顺序返回。例如,你可以按姓名对人员列表进行排序,然后按年龄对列表进行排序,从而得到一个按年龄排序的列表,其中年龄相同的人员按姓名排序。
(
sort()
的所有更改均由 Raymond Hettinger 贡献。)有一个新的内置函数
sorted(iterable)
,它的工作方式类似于就地list.sort()
方法,但可以在表达式中使用。区别在于输入可以是任何可迭代对象;
对新形成的副本进行排序,保持原始副本不变;并且
表达式返回新的排序副本
>>> L = [9,7,8,3,2,4,1,6,5] >>> [10+i for i in sorted(L)] # usable in a list comprehension [11, 12, 13, 14, 15, 16, 17, 18, 19] >>> L # original is left unchanged [9,7,8,3,2,4,1,6,5] >>> sorted('Monty Python') # any iterable may be an input [' ', 'M', 'P', 'h', 'n', 'n', 'o', 'o', 't', 't', 'y', 'y'] >>> # List the contents of a dict sorted by key values >>> colormap = dict(red=1, blue=2, green=3, black=4, yellow=5) >>> for k, v in sorted(colormap.iteritems()): ... print k, v ... black 4 blue 2 green 3 red 1 yellow 5
(由 Raymond Hettinger 贡献。)
整数运算将不再触发
OverflowWarning
。OverflowWarning
警告将在 Python 2.5 中消失。解释器获得了一个新的开关
-m
,它接受一个名称,在sys.path
上搜索相应的模块,并将该模块作为脚本运行。例如,现在可以使用python -m profile
运行 Python 分析器。(由 Nick Coghlan 贡献。)eval(expr, globals, locals)
和execfile(filename, globals, locals)
函数以及exec
语句现在接受任何映射类型作为 locals 参数。以前,这必须是常规的 Python 字典。(由 Raymond Hettinger 贡献。)zip()
内置函数和itertools.izip()
现在在不带参数调用时返回一个空列表。以前,它们会引发TypeError
异常。这使得它们更适合与可变长度的参数列表一起使用>>> def transpose(array): ... return zip(*array) ... >>> transpose([(1,2,3), (4,5,6)]) [(1, 4), (2, 5), (3, 6)] >>> transpose([]) []
(由 Raymond Hettinger 贡献。)
在导入模块时遇到故障不再在
sys.modules
中留下部分初始化的模块对象。留下的不完整的模块对象会迷惑对同一模块的进一步导入,使其成功,从而导致令人困惑的错误。(由 Tim Peters 修复。)None
现在是一个常量;将新值绑定到名称None
的代码现在是语法错误。(由 Raymond Hettinger 贡献。)
优化¶
列表和元组切片的内部循环已得到优化,现在运行速度快了大约三分之一。字典的内部循环也得到了优化,从而提高了
keys()
、values()
、items()
、iterkeys()
、itervalues()
和iteritems()
的性能。(由 Raymond Hettinger 贡献。)用于增长和缩小列表的机制针对速度和空间效率进行了优化。由于更高效的代码路径和更少地使用底层系统
realloc()
,从列表中追加和弹出现在运行得更快。列表推导式也受益。list.extend()
也得到了优化,并且不再在扩展基本列表之前将其参数转换为临时列表。(由 Raymond Hettinger 贡献。)list()
、tuple()
、map()
、filter()
和zip()
现在使用提供__len__()
方法的非序列参数运行速度快了几倍。(由 Raymond Hettinger 贡献。)方法
list.__getitem__()
、dict.__getitem__()
和dict.__contains__()
现在实现为method_descriptor
对象,而不是wrapper_descriptor
对象。这种访问形式使其性能提高了一倍,并使其更适合用作函数式参数:map(mydict.__getitem__, keylist)
。(由 Raymond Hettinger 贡献。)添加了一个新的操作码
LIST_APPEND
,它简化了列表推导式的生成的字节码,并将其速度提高了大约三分之一。(由 Raymond Hettinger 贡献。)窥孔字节码优化器已得到改进,可生成更短、更快的字节码;值得注意的是,生成的字节码更具可读性。(由 Raymond Hettinger 增强。)
形如
s = s + "abc"
和s += "abc"
语句中的字符串连接现在在某些情况下执行得更有效率。这种优化不会出现在其他 Python 实现中,例如 Jython,因此你不应该依赖它;当你想要有效地将大量字符串粘合在一起时,仍然建议使用字符串的join()
方法。(由 Armin Rigo 贡献。)
2.4 优化的最终结果是,Python 2.4 运行 pystone 基准测试的速度比 Python 2.3 快约 5%,比 Python 2.2 快 35%。(pystone 不是一个特别好的基准测试,但它是最常用的 Python 性能测量方法。你自己的应用程序可能会显示 Python 2.4 带来的更大或更小的收益。)
新的、改进的和已弃用的模块¶
像往常一样,Python 的标准库收到了一些增强功能和错误修复。以下是按模块名称字母顺序排列的最显著更改的部分列表。有关更完整的更改列表,请查阅源代码树中的 Misc/NEWS
文件,或查看 CVS 日志以获取所有详细信息。
asyncore
模块的loop()
函数现在有一个 count 参数,允许您执行有限次数的轮询循环。默认值仍然是无限循环。base64
模块现在对 Base64、Base32 和 Base16 编码和解码具有更完整的 RFC 3548 支持,包括可选的大小写折叠和可选的替代字母表。(由 Barry Warsaw 贡献。)bisect
模块现在有一个底层的 C 实现,以提高性能。(由 Dmitry Vasiliev 贡献。)由 Hye-Shik Chang 维护的东亚编解码器 CJKCodecs 集合已集成到 2.4 中。新的编码是
中文(中国):gb2312、gbk、gb18030、big5hkscs、hz
中文(中华民国):big5、cp950
- 日语:cp932、euc-jis-2004、euc-jp、euc-jisx0213、iso-2022-jp、
iso-2022-jp-1、iso-2022-jp-2、iso-2022-jp-3、iso-2022-jp-ext、iso-2022-jp-2004、shift-jis、shift-jisx0213、shift-jis-2004
韩语:cp949、euc-kr、johab、iso-2022-kr
添加了一些其他新编码:HP Roman8、ISO_8859-11、ISO_8859-16、PCTP-154 和 TIS-620。
UTF-8 和 UTF-16 编解码器现在可以更好地处理接收到的部分输入。以前,
StreamReader
类会尝试读取更多数据,从而无法从流中恢复解码。现在,read()
方法将返回尽可能多的数据,并且将来的调用将从上次调用停止的位置恢复解码。(由 Walter Dörwald 实现。)有一个新的
collections
模块,用于各种专门的集合数据类型。目前它只包含一种类型,deque
,一个双端队列,支持从两端高效地添加和删除元素>>> from collections import deque >>> d = deque('ghi') # make a new deque with three items >>> d.append('j') # add a new entry to the right side >>> d.appendleft('f') # add a new entry to the left side >>> d # show the representation of the deque deque(['f', 'g', 'h', 'i', 'j']) >>> d.pop() # return and remove the rightmost item 'j' >>> d.popleft() # return and remove the leftmost item 'f' >>> list(d) # list the contents of the deque ['g', 'h', 'i'] >>> 'h' in d # search the deque True
一些模块,例如
Queue
和threading
模块,现在利用collections.deque
来提高性能。(由 Raymond Hettinger 贡献。)ConfigParser
类已略有增强。read()
方法现在返回已成功解析的文件列表,如果传递的 value 参数不是字符串,则set()
方法会引发TypeError
。(由 John Belmonte 和 David Goodger 贡献。)curses
模块现在支持 ncurses 扩展use_default_colors()
。在终端支持透明度的平台上,这使得可以使用透明背景。(由 Jörg Lehmann 贡献。)difflib
模块现在包含一个HtmlDiff
类,该类创建一个 HTML 表格,显示文本的两个版本的并排比较。(由 Dan Gass 贡献。)email
包已更新到 3.0 版本,该版本删除了各种已弃用的 API 并移除了对 Python 2.3 之前版本的支持。该软件包的 3.0 版本对 MIME 消息使用新的增量解析器,该解析器可在email.FeedParser
模块中使用。新解析器不需要将整个消息读取到内存中,并且如果消息格式不正确也不会引发异常;相反,它会在消息的defect
属性中记录任何问题。(由 Anthony Baxter、Barry Warsaw、Thomas Wouters 和其他人开发。)heapq
模块已转换为 C。由此带来的十倍速度提升使该模块适合处理大量数据。此外,该模块还有两个新函数nlargest()
和nsmallest()
,它们使用堆来查找数据集中的 N 个最大或最小值,而无需付出完全排序的代价。(由 Raymond Hettinger 贡献。)httplib
模块现在包含各种与 HTTP 相关的 RFC 文档中定义的 HTTP 状态代码的常量。常量具有诸如OK
、CREATED
、CONTINUE
和MOVED_PERMANENTLY
等名称;使用 pydoc 获取完整列表。(由 Andrew Eland 贡献。)imaplib
模块现在支持 IMAP 的 THREAD 命令(由 Yves Dionne 贡献)和新的deleteacl()
和myrights()
方法(由 Arnaud Mazin 贡献)。itertools
模块获得了一个groupby(iterable[, *func*])
函数。iterable 是可以迭代以返回元素流的东西,可选的 func 参数是一个接受元素并返回键值的函数;如果省略,则键只是元素本身。groupby()
然后将元素分组为具有匹配键值的子序列,并返回一系列包含键值和子序列迭代器的 2 元组。这是一个使其更清晰的示例。key 函数只是返回一个数字是偶数还是奇数,因此
groupby()
的结果是返回连续的奇数或偶数运行。>>> import itertools >>> L = [2, 4, 6, 7, 8, 9, 11, 12, 14] >>> for key_val, it in itertools.groupby(L, lambda x: x % 2): ... print key_val, list(it) ... 0 [2, 4, 6] 1 [7] 0 [8] 1 [9, 11] 0 [12, 14] >>>
groupby()
通常与排序的输入一起使用。groupby()
的逻辑类似于 Unixuniq
过滤器,这使其便于消除、计数或识别重复元素>>> word = 'abracadabra' >>> letters = sorted(word) # Turn string into a sorted list of letters >>> letters ['a', 'a', 'a', 'a', 'a', 'b', 'b', 'c', 'd', 'r', 'r'] >>> for k, g in itertools.groupby(letters): ... print k, list(g) ... a ['a', 'a', 'a', 'a', 'a'] b ['b', 'b'] c ['c'] d ['d'] r ['r', 'r'] >>> # List unique letters >>> [k for k, g in groupby(letters)] ['a', 'b', 'c', 'd', 'r'] >>> # Count letter occurrences >>> [(k, len(list(g))) for k, g in groupby(letters)] [('a', 5), ('b', 2), ('c', 1), ('d', 1), ('r', 2)]
(由 Hye-Shik Chang 贡献。)
itertools
还获得了一个名为tee(iterator, N)
的函数,该函数返回 N 个独立的迭代器,这些迭代器复制 iterator。如果省略 N,则默认值为 2。>>> L = [1,2,3] >>> i1, i2 = itertools.tee(L) >>> i1,i2 (<itertools.tee object at 0x402c2080>, <itertools.tee object at 0x402c2090>) >>> list(i1) # Run the first iterator to exhaustion [1, 2, 3] >>> list(i2) # Run the second iterator to exhaustion [1, 2, 3]
请注意,
tee()
必须保留迭代器返回的值的副本;在最坏的情况下,它可能需要保留所有值。因此,如果前导迭代器在长输入流中远远领先于后导迭代器,则应谨慎使用此方法。如果分隔很大,那么您不妨改用list()
。当迭代器彼此紧密跟踪时,tee()
是理想的。可能的应用包括书签、窗口或前瞻迭代器。(由 Raymond Hettinger 贡献。)向
locale
模块添加了许多函数,例如bind_textdomain_codeset()
来指定特定的编码和一系列l*gettext()
函数,这些函数返回所选编码的消息。(由 Gustavo Niemeyer 贡献。)为简化日志配置,
logging
包的basicConfig()
函数添加了一些关键字参数。默认行为是将消息记录到标准错误输出,但可以通过指定各种关键字参数来记录到特定文件,更改日志格式或设置日志级别。例如:import logging logging.basicConfig(filename='/var/log/application.log', level=0, # Log all messages format='%(levelname):%(process):%(thread):%(message)')
logging
包的其他新增功能包括一个方便的log(level, msg)
方法,以及一个TimedRotatingFileHandler
类,该类会在定时的时间间隔轮换其日志文件。该模块已经有一个RotatingFileHandler
类,该类在文件超过特定大小时轮换日志。这两个类都派生自一个新的BaseRotatingHandler
类,该类可用于实现其他轮换处理程序。(由 Vinay Sajip 实现的更改。)
marshal
模块现在在解包数据结构时共享驻留字符串。这可能会缩小某些 pickle 字符串的大小,但主要作用是使.pyc
文件显著缩小。(由 Martin von Löwis 贡献。)nntplib
模块的NNTP
类增加了description()
和descriptions()
方法,用于检索单个新闻组或一系列新闻组的描述。(由 Jürgen A. Erhard 贡献。)为
operator
模块添加了两个新函数,attrgetter(attr)
和itemgetter(index)
。这两个函数都返回一个可调用对象,该对象接受一个参数并返回相应的属性或项;当与map()
或sorted()
一起使用时,这些可调用对象是极佳的数据提取器。例如:>>> L = [('c', 2), ('d', 1), ('a', 4), ('b', 3)] >>> map(operator.itemgetter(0), L) ['c', 'd', 'a', 'b'] >>> map(operator.itemgetter(1), L) [2, 1, 4, 3] >>> sorted(L, key=operator.itemgetter(1)) # Sort list by second tuple item [('d', 1), ('c', 2), ('b', 3), ('a', 4)]
(由 Raymond Hettinger 贡献。)
optparse
模块以各种方式进行了更新。该模块现在通过gettext.gettext()
传递其消息,从而可以对 Optik 的帮助和错误消息进行国际化。选项的帮助消息现在可以包含字符串'%default'
,该字符串将被选项的默认值替换。(由 Greg Ward 贡献。)长期计划是在未来的某个 Python 版本中弃用
rfc822
模块,而支持email
包。为此,email.Utils.formatdate
函数已更改为可作为rfc822.formatdate()
的替代品使用。您可能需要考虑到这一点来编写新的电子邮件处理代码。(由 Anthony Baxter 实现的更改。)在
os
模块中添加了一个新的urandom(n)
函数,该函数返回一个包含 n 个字节随机数据的字符串。此函数提供了对特定于平台的随机性来源的访问,例如 Linux 上的/dev/urandom
或 Windows CryptoAPI。(由 Trevor Perrin 贡献。)另一个新函数:如果 path 指定的文件存在,则
os.path.lexists(path)
返回 true,无论它是否是符号链接。这与现有的os.path.exists(path)
函数不同,如果 path 是指向不存在的目的地的符号链接,则该函数返回 false。(由 Beni Cherniavsky 贡献。)在
posix
模块中添加了一个新的getsid()
函数,该模块是os
模块的基础。(由 J. Raynor 贡献。)poplib
模块现在支持通过 SSL 的 POP。(由 Hector Urtubia 贡献。)profile
模块现在可以分析 C 扩展函数。(由 Nick Bastin 贡献。)random
模块有一个名为getrandbits(N)
的新方法,该方法返回长度为 N 位的长整数。现有的randrange()
方法现在在适当的情况下使用getrandbits()
,从而更有效地生成任意大的随机数。(由 Raymond Hettinger 贡献。)re
模块接受的正则表达式语言已扩展为简单的条件表达式,写为(?(group)A|B)
。group 是一个数字组 ID 或一个在表达式前面用(?P<group>...)
定义的组名。如果指定的组匹配,正则表达式模式 A 将针对字符串进行测试;如果该组不匹配,则将使用模式 B。(由 Gustavo Niemeyer 贡献。)感谢 Gustavo Niemeyer 的大量工作,
re
模块也不再是递归的。在递归正则表达式引擎中,某些模式会导致消耗大量的 C 堆栈空间,并且可能导致堆栈溢出。例如,如果将一个包含 30000 个字符a
的字符串与表达式(a|b)+
匹配,则每个字符都会消耗一个堆栈帧。Python 2.3 尝试检查堆栈溢出并引发RuntimeError
异常,但某些模式可能会绕过检查,如果运气不好,Python 可能会出现段错误。Python 2.4 的正则表达式引擎可以毫无问题地匹配此模式。signal
模块现在对signal.signal()
函数的参数执行更严格的错误检查。例如,您不能在SIGKILL
信号上设置处理程序;以前版本的 Python 会静默接受此操作,但 2.4 会引发RuntimeError
异常。为
socket
模块添加了两个新函数。socketpair()
返回一对连接的套接字,而getservbyport(port)
查找给定端口号的服务名称。(由 Dave Cole 和 Barry Warsaw 贡献。)sys.exitfunc()
函数已被弃用。代码应使用现有的atexit
模块,该模块可以正确处理调用多个退出函数。最终,sys.exitfunc()
将成为一个纯粹的内部接口,仅供atexit
访问。现在,
tarfile
模块默认生成 GNU 格式的 tar 文件。(由 Lars Gustäbel 贡献。)现在,
threading
模块提供了一种非常简单的方法来支持线程局部数据。该模块包含一个local
类,其属性值对于不同的线程是局部的。import threading data = threading.local() data.number = 42 data.url = ('www.python.org', 80)
其他线程可以为
number
和url
属性分配和检索它们自己的值。您可以子类化local
来初始化属性或添加方法。(由 Jim Fulton 贡献。)现在,
timeit
模块在计时循环期间会自动禁用周期性垃圾回收。此更改使连续计时更具可比性。(由 Raymond Hettinger 贡献。)现在,
weakref
模块支持更广泛的对象,包括 Python 函数、类实例、集合、冻结集合、双端队列、数组、文件、套接字和正则表达式模式对象。(由 Raymond Hettinger 贡献。)现在,
xmlrpclib
模块支持多调用扩展,用于在单个 HTTP 操作中传输多个 XML-RPC 调用。(由 Brian Quinlan 贡献。)mpz
、rotor
和xreadlines
模块已被移除。
doctest¶
感谢 Edward Loper 和 Tim Peters,doctest
模块进行了大量的重构。测试仍然可以像运行 doctest.testmod()
一样简单,但重构允许以各种方式自定义模块的操作
新的 DocTestFinder
类从给定对象的 docstring 中提取测试
def f (x, y):
""">>> f(2,2)
4
>>> f(3,2)
6
"""
return x*y
finder = doctest.DocTestFinder()
# Get list of DocTest instances
tests = finder.find(f)
新的 DocTestRunner
类然后运行单个测试,并可以生成结果摘要
runner = doctest.DocTestRunner()
for t in tests:
tried, failed = runner.run(t)
runner.summarize(verbose=1)
上面的示例产生以下输出
1 items passed all tests:
2 tests in f
2 tests in 1 items.
2 passed and 0 failed.
Test passed.
DocTestRunner
使用 OutputChecker
类的实例来比较预期输出和实际输出。这个类接受许多自定义其行为的不同标志;有抱负的用户也可以编写一个全新的 OutputChecker
子类。
默认的输出检查器提供了许多方便的功能。例如,使用 doctest.ELLIPSIS
选项标志,预期输出中的省略号(...
)匹配任何子字符串,从而更容易适应略有不同的输出
def o (n):
""">>> o(1)
<__main__.C instance at 0x...>
>>>
"""
另一个特殊字符串 <BLANKLINE>
匹配一个空行
def p (n):
""">>> p(1)
<BLANKLINE>
>>>
"""
另一个新功能是通过指定 doctest.REPORT_UDIFF
(统一差异)、doctest.REPORT_CDIFF
(上下文差异)或 doctest.REPORT_NDIFF
(增量样式)选项标志来生成输出的 diff 样式显示。例如
def g (n):
""">>> g(4)
here
is
a
lengthy
>>>"""
L = 'here is a rather lengthy list of words'.split()
for word in L[:n]:
print word
使用指定的 doctest.REPORT_UDIFF
运行上述函数的测试,您将获得以下输出
**********************************************************************
File "t.py", line 15, in g
Failed example:
g(4)
Differences (unified diff with -expected +actual):
@@ -2,3 +2,3 @@
is
a
-lengthy
+rather
**********************************************************************
构建和 C API 更改¶
以下是 Python 构建过程和 C API 的一些更改
为扩展函数的常用返回值添加了三个新的便捷宏:
Py_RETURN_NONE
、Py_RETURN_TRUE
和Py_RETURN_FALSE
。(由 Brett Cannon 贡献。)另一个新宏
Py_CLEAR
,减少 obj 的引用计数并将 obj 设置为空指针。(由 Jim Fulton 贡献。)一个新函数
PyTuple_Pack(N, obj1, obj2, ..., objN)
,从 Python 对象的变长参数列表构造元组。(由 Raymond Hettinger 贡献。)一个新函数
PyDict_Contains(d, k)
,实现快速字典查找,而不会屏蔽查找过程中引发的异常。(由 Raymond Hettinger 贡献。)Py_IS_NAN(X) 宏返回 1,如果其 float 或 double 参数 X 是 NaN。(由 Tim Peters 贡献。)
C 代码可以使用新的
PyEval_ThreadsInitialized()
函数来判断是否已执行任何线程操作,从而避免不必要的锁定。如果此函数返回 false,则不需要锁定操作。(由 Nick Coghlan 贡献。)一个新函数
PyArg_VaParseTupleAndKeywords()
与PyArg_ParseTupleAndKeywords()
相同,但接受va_list
而不是多个参数。(由 Greg Chapman 贡献。)新的方法标志
METH_COEXIST
,允许在槽中定义的函数与具有相同名称的PyCFunction
共存。这可以将诸如set.__contains__()
之类的方法的访问时间减半。(由 Raymond Hettinger 贡献。)现在,Python 可以使用额外的分析功能进行构建,旨在帮助开发 Python 核心的人员。向 configure 脚本提供
--enable-profiling
将允许您使用 gprof 分析解释器,并提供--with-tsc
开关启用使用奔腾的时间戳计数器寄存器进行分析。请注意,--with-tsc
开关的命名略有不妥,因为分析功能也适用于 PowerPC 平台,尽管该处理器架构不将该寄存器称为“TSC 寄存器”。(由 Jeremy Hylton 贡献。)tracebackobject
类型已重命名为PyTracebackObject
。
特定于端口的更改¶
Windows 端口现在可以在 MSVC++ 7.1 以及 6 版本下构建。(由 Martin von Löwis 贡献。)
移植到 Python 2.4¶
本节列出先前描述的可能需要更改代码的更改
左移和过大的十六进制/八进制常量不再触发
FutureWarning
并返回限制为 32 或 64 位的值;相反,它们返回长整数。整数运算将不再触发
OverflowWarning
。OverflowWarning
警告将在 Python 2.5 中消失。zip()
内置函数和itertools.izip()
现在返回一个空列表,而不是在不带参数调用时引发TypeError
异常。您不能再比较
date
和datetime
模块提供的实例。不同类的两个实例现在将始终不相等,并且相对比较(<
,>
)将引发TypeError
。dircache.listdir()
现在将异常传递给调用者,而不是返回空列表。LexicalHandler.startDTD()
过去接收公共 ID 和系统 ID 的顺序错误。这已被纠正;依赖于错误顺序的应用程序需要修复。如果省略了 mutate 参数且相关,
fcntl.ioctl()
现在会发出警告。tarfile
模块现在默认生成 GNU 格式的 tar 文件。在导入模块时遇到失败不再在
sys.modules
中留下部分初始化的模块对象。None
现在是一个常量;将新值绑定到名称None
的代码现在是语法错误。signals.signal()
函数现在会为某些非法值引发RuntimeError
异常;以前这些错误会静默地传递。例如,您不能再在SIGKILL
信号上设置处理程序。
鸣谢¶
作者要感谢以下人员为本文的各种草稿提供建议、更正和帮助:Koray Can、Hye-Shik Chang、Michael Dyck、Raymond Hettinger、Brian Hurt、Hamish Lawson、Fredrik Lundh、Sean Reifschneider、Sadruddin Rejeb。