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 模块保留在标准库中,如果您希望子类化 SetImmutableSet 类,它可能会很有用。目前没有计划弃用该模块。

另请参阅

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'

在编写模板字符串时,很容易忘记右括号后面的 is。 如果模板在 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):
       ...

@classmethodmeth=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() 所做的那样。)

stdinstdoutstderr 指定子进程的输入、输出和错误流将是什么。您可以提供文件对象或文件描述符,也可以使用常量 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 的标准库中。它包含两个类,DecimalContextDecimal 实例表示数字,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 数字可以与 mathcmath 模块一起使用,但请注意,在执行操作之前,它们将立即转换为浮点数,从而可能导致精度和准确性的损失。您还将得到一个常规的浮点数而不是 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_DOWNROUND_CEILINGROUND_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() 方法中添加了三个关键字参数,cmpkeyreverse。这些参数使 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 贡献。)

  • 整数运算将不再触发 OverflowWarningOverflowWarning 警告将在 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
    

    一些模块,例如 Queuethreading 模块,现在利用 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 状态代码的常量。常量具有诸如 OKCREATEDCONTINUEMOVED_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() 的逻辑类似于 Unix uniq 过滤器,这使其便于消除、计数或识别重复元素

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

    其他线程可以为 numberurl 属性分配和检索它们自己的值。您可以子类化 local 来初始化属性或添加方法。(由 Jim Fulton 贡献。)

  • 现在,timeit 模块在计时循环期间会自动禁用周期性垃圾回收。此更改使连续计时更具可比性。(由 Raymond Hettinger 贡献。)

  • 现在,weakref 模块支持更广泛的对象,包括 Python 函数、类实例、集合、冻结集合、双端队列、数组、文件、套接字和正则表达式模式对象。(由 Raymond Hettinger 贡献。)

  • 现在,xmlrpclib 模块支持多调用扩展,用于在单个 HTTP 操作中传输多个 XML-RPC 调用。(由 Brian Quinlan 贡献。)

  • mpzrotorxreadlines 模块已被移除。

cookielib

cookielib 库支持 HTTP Cookie 的客户端处理,镜像 Cookie 模块的服务器端 Cookie 支持。Cookie 存储在 cookie jar 中;该库透明地将 Web 服务器提供的 cookie 存储在 cookie jar 中,并在连接到服务器时从 jar 中获取 cookie。与 Web 浏览器一样,策略对象控制是否接受 cookie。

为了跨会话存储 cookie,提供了 cookie jar 的两种实现:一种以 Netscape 格式存储 cookie,以便应用程序可以使用 Mozilla 或 Lynx cookie 文件,另一种以与 Perl libwww 库相同的格式存储 cookie。

urllib2 已更改为与 cookielib 交互:HTTPCookieProcessor 管理一个 cookie jar,该 cookie jar 在访问 URL 时使用。

此模块由 John J. Lee 贡献。

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_NONEPy_RETURN_TRUEPy_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 位的值;相反,它们返回长整数。

  • 整数运算将不再触发 OverflowWarningOverflowWarning 警告将在 Python 2.5 中消失。

  • zip() 内置函数和 itertools.izip() 现在返回一个空列表,而不是在不带参数调用时引发 TypeError 异常。

  • 您不能再比较 datedatetime 模块提供的实例。不同类的两个实例现在将始终不相等,并且相对比较(<, >)将引发 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。