Python 2.1 的新增功能 — Python 文档

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

Python 2.1 中的新功能

作者
是 库克林

介绍

本文解释了 Python 2.1 中的新功能。 虽然 2.1 中的变化没有 Python 2.0 那么多,但仍然有一些惊喜。 2.1 是第一个通过使用 Python Enhancement Proposals 或 PEP 来引导的版本,因此大多数重大更改都附带 PEP,这些 PEP 为更改提供了更完整的文档和设计原理。 本文并不试图完整地记录新功能,而只是为 Python 程序员提供新功能的概述。 有关您特别感兴趣的任何新功能的更多详细信息,请参阅 Python 2.1 文档或特定 PEP。

Python 开发团队最近的一个目标是加快新版本的发布速度,每 6 到 9 个月就会发布一个新版本。 2.1 是第一个以这种更快的速度发布的版本,第一个 alpha 版本出现在 2.0 最终版本发布 3 个月后的 1 月。

Python 2.1 的最终版本于 2001 年 4 月 17 日发布。


PEP 227:嵌套作用域

Python 2.1 中最大的变化是 Python 的范围规则。 在 Python 2.0 中,在任何给定时间最多有三个命名空间用于查找变量名称:本地、模块级和内置命名空间。 这常常让人们感到惊讶,因为它不符合他们的直觉预期。 例如,嵌套递归函数定义不起作用:

def f():
    ...
    def g(value):
        ...
        return g(value-1) + 1
    ...

函数 g() 将始终引发 NameError 异常,因为名称 g 的绑定不在其本地命名空间或模块级命名空间中。 这在实践中不是什么大问题(你多久像这样递归地定义内部函数?),但这也使得使用 lambda 表达式变得笨拙,这在实践中是一个问题。 在使用 lambda 的代码中,您通常可以通过将局部变量作为参数的默认值传递来发现被复制的局部变量。

def find(self, name):
    "Return list of any entries equal to 'name'"
    L = filter(lambda x, name=name: x == name,
               self.list_attribute)
    return L

因此,以强函数风格编写的 Python 代码的可读性受到很大影响。

Python 2.1 最重要的变化是在语言中添加了静态作用域来解决这个问题。 作为第一个效果,在上面的例子中 name=name 默认参数现在是不必要的。 简而言之,当给定的变量名未在函数内赋值时(通过赋值,或 defclassimport 语句),对变量的引用将在封闭作用域的本地命名空间中查找。 可以在 PEP 中找到对规则的更详细解释以及对实现的剖析。

对于在模块级别使用相同变量名称和作为包含更多函数定义的函数中的局部变量的代码,此更改可能会导致一些兼容性问题。 不过,这似乎不太可能,因为这样的代码一开始读起来会很混乱。

更改的一个副作用是 from module import *exec 语句在某些条件下在函数作用域内是非法的。 Python 参考手册一直说 from module import * 只在模块的顶层是合法的,但 CPython 解释器之前从未强制执行过。 作为嵌套作用域实现的一部分,将 Python 源代码转换为字节码的编译器必须生成不同的代码来访问包含作用域中的变量。 from module import *exec 使编译器无法弄清楚这一点,因为它们向本地命名空间添加了在编译时不可知的名称。 因此,如果函数包含函数定义或带有自由变量的 lambda 表达式,编译器将通过引发 SyntaxError 异常来标记它。

为了让前面的解释更清楚一些,这里有一个例子:

x = 1
def f():
    # The next line is a syntax error
    exec 'x=2'
    def g():
        return x

包含 exec 语句的第 4 行是一个语法错误,因为 exec 将定义一个名为 x 的新局部变量,其值应由 g() 访问。

这不应该是一个很大的限制,因为 exec 在大多数 Python 代码中很少使用(并且当它被使用时,它通常是一个糟糕设计的标志)。

兼容性问题导致逐渐引入嵌套作用域; 在 Python 2.1 中,它们默认不启用,但可以通过使用 future 语句在模块内打开,如 PEP 236 中所述。 (有关 PEP 236 的进一步讨论,请参阅以下部分。)在 Python 2.2 中,嵌套作用域将成为默认设置,并且无法将其关闭,但用户将拥有拥有 2.1 的整个生命周期来修复因引入而导致的任何损坏。

也可以看看

PEP 227 - 静态嵌套范围
由 Jeremy Hylton 编写和实施。


PEP 236:__future__ 指令

对嵌套作用域的反应是对 2.1 版本破坏代码危险的广泛关注,它足以让 Pythoneers 采取更保守的方法。 这种方法包括在版本 N 中引入一个启用可选功能的约定,这将在版本 N+1 中成为强制性的。

语法使用 from...import 语句,使用保留模块名称 __future__。 可以通过以下语句启用嵌套范围:

from __future__ import nested_scopes

虽然它看起来像一个普通的 import 语句,但它不是; 关于未来声明的放置位置有严格的规定。 它们只能位于模块的顶部,并且必须位于任何 Python 代码或常规 import 语句之前。 这是因为此类语句会影响 Python 字节码编译器解析代码和生成字节码的方式,因此它们必须位于任何会导致生成字节码的语句之前。

也可以看看

PEP 236 - 回到 __未来__
由 Tim Peters 编写,主要由 Jeremy Hylton 实施。


PEP 207:丰富的比较

在早期版本中,Python 支持对用户定义的类和扩展类型进行比较是非常简单的。 类可以实现一个 __cmp__() 方法,该方法被赋予一个类的两个实例,如果它们相等,则只能返回 0,否则返回 +1 或 -1; 该方法不能引发异常或返回布尔值以外的任何内容。 Numeric Python 的用户经常发现这个模型太弱和限制性强,因为在使用 numeric Python 的数字运算程序中,能够对两个矩阵执行元素比较会更有用,返回一个包含结果的矩阵每个元素的给定比较。 如果两个矩阵的大小不同,则比较必须能够引发异常以发出错误信号。

在 Python 2.1 中,为了支持这种需求,添加了丰富的比较。 Python 类现在可以单独重载 <<=>>===!= ] 操作。 新的魔法方法名称是:

手术 方法名称
< __lt__()
<= __le__()
> __gt__()
>= __ge__()
== __eq__()
!= __ne__()

(魔术方法以相应的 Fortran 运算符 .LT. 命名。 .LE., &C。 数字程序员几乎肯定对这些名称非常熟悉,并且会发现它们很容易记住。)

这些魔术方法中的每一个都采用 method(self, other) 形式,其中 self 将是运算符左侧的对象,而 other 将是运算符左侧的对象右侧。 例如,表达式 A < B 将导致调用 A.__lt__(B)

这些魔术方法中的每一个都可以返回任何内容:布尔值、矩阵、列表或任何其他 Python 对象。 或者,如果比较不可能、不一致或无意义,它们可以引发异常。

内置的 cmp(A,B) 函数可以使用丰富的比较机制,现在接受一个可选参数指定使用哪个比较操作; 这是作为字符串之一给出的 "<""<="">"">=""==""!=" . 如果在没有可选的第三个参数的情况下调用,cmp() 将只返回 -1、0 或 +1,就像在以前的 Python 版本中一样; 否则它将调用适当的方法并可以返回任何 Python 对象。

C程序员也有相应的兴趣变化; 类型对象中有一个新的插槽 tp_richcmp 和一个用于执行给定丰富比较的 API。 我不会在这里介绍 C API,但会向您推荐 PEP 207 或 2.1 的 C API 文档,以获取相关函数的完整列表。

也可以看看

PEP 207 - 丰富的比较
由 Guido van Rossum 编写,主要基于 David Ascher 的早期工作,由 Guido van Rossum 实施。


PEP 230:警告框架

在其存在的 10 年中,Python 在此过程中积累了一定数量的过时模块和功能。 很难知道何时可以安全地删除某个功能,因为无法知道有多少代码使用它——也许没有程序依赖于该功能,或者很多程序都依赖该功能。 为了能够以更结构化的方式删除旧功能,添加了一个警告框架。 当 Python 开发人员想要摆脱某个功能时,它会在下一版本的 Python 中首先触发警告。 接下来的 Python 版本可以删除该功能,用户将有一个完整的发布周期来删除旧功能的使用。

Python 2.1 添加了要在此方案中使用的警告框架。 它添加了一个 warnings 模块,该模块提供发出警告和过滤掉您不想显示的警告的功能。 第三方模块也可以使用这个框架来弃用他们不再希望支持的旧功能。

例如,在 Python 2.1 中 regex 模块已弃用,因此导入它会导致打印警告:

>>> import regex
__main__:1: DeprecationWarning: the regex module
         is deprecated; please use the re module
>>>

可以通过调用 warnings.warn() 函数来发出警告:

warnings.warn("feature X no longer supported")

第一个参数是警告信息; 附加的可选参数可用于指定特定的警告类别。

可以添加过滤器以禁用某些警告; 可以将正则表达式模式应用于消息或模块名称以抑制警告。 例如,您可能有一个使用 regex 模块的程序,现在不想花时间将其转换为使用 re 模块。 可以通过调用来抑制警告

import warnings
warnings.filterwarnings(action = 'ignore',
                        message='.*regex module is deprecated',
                        category=DeprecationWarning,
                        module = '__main__')

这添加了一个过滤器,该过滤器仅适用于在 __main__ 模块中触发的类 DeprecationWarning 的警告,并应用正则表达式以仅匹配有关 regex 的消息模块被弃用,并将导致此类警告被忽略。 警告也可以只打印一次,每次执行违规代码时都打印,或者变成会导致程序停止的异常(当然,除非异常以通常的方式被捕获)。

Python 的 C API 中还添加了用于发出警告的函数; 有关详细信息,请参阅 PEP 230 或 Python 的 API 文档。

也可以看看

PEP 5 - 语言进化指南
由 Paul Prescod 编写,用于指定从 Python 中删除旧功能时要遵循的程序。 本 PEP 中描述的政策尚未被正式采用,但最终的政策可能与 Prescod 的提议不会有太大差异。
PEP 230 - 警告框架
由 Guido van Rossum 编写和实施。


PEP 229:新构建系统

在编译 Python 时,用户必须进入并编辑 Modules/Setup 文件才能启用各种附加模块; 默认设置相对较小,仅限于在大多数 Unix 平台上编译的模块。 这意味着在具有更多功能的 Unix 平台上,最显着的是 Linux,Python 安装通常不包含它们可能包含的所有有用模块。

Python 2.0 添加了 Distutils,这是一组用于分发和安装扩展的模块。 在 Python 2.1 中,Distutils 用于编译大部分扩展模块的标准库,自动检测当前机器支持哪些扩展模块。 希望这将使 Python 安装更容易,功能更强大。

不必为了启用模块而编辑 Modules/Setup 文件,Python 源代码分发的顶层目录中的 setup.py 脚本在构建时运行,并尝试发现哪些模块可以通过检查系统上的模块和头文件来启用。 如果在 Modules/Setup 中配置了模块,则 setup.py 脚本不会尝试编译该模块,而是会遵循 Modules/Setup 文件的内容。 这提供了一种方法来指定特定平台所需的任何奇怪的命令行标志或库。

在对构建机制的另一个影响深远的变化中,Neil Schemenauer 重组了一些东西,因此 Python 现在使用一个非递归的 makefile,而不是顶层目录和 Python/Parser/Objects/Modules/ 子目录。 这使得构建 Python 更快,也使得破解 Makefile 更清晰、更简单。

也可以看看

PEP 229 - 使用 Distutils 构建 Python
由 AM 编写和实施 古奇灵。


PEP 205:弱引用

弱引用可通过 weakref 模块获得,是 Python 程序员工具箱中一种次要但有用的新数据类型。

存储对对象的引用(例如,在字典或列表中)具有使该对象永远保持活动状态的副作用。 在某些特定情况下,这种行为是不可取的,对象缓存是最常见的一种,另一种是数据结构(如树)中的循环引用。

例如,考虑一个记忆函数,它通过将函数的参数及其结果存储在字典中来缓存另一个函数 f(x) 的结果:

_cache = {}
def memoize(x):
    if _cache.has_key(x):
        return _cache[x]

    retval = f(x)

    # Cache the returned object
    _cache[x] = retval

    return retval

这个版本适用于简单的东西,比如整数,但它有一个副作用; _cache 字典包含对返回值的引用,因此在 Python 进程退出并清理之前它们永远不会被释放。 这对于整数来说不是很明显,但是如果 f() 返回一个对象,或者一个占用大量内存的数据结构,这可能是一个问题。

弱引用提供了一种实现缓存的方法,该缓存不会让对象在它们的时间之外保持活动状态。 如果一个对象只能通过弱引用访问,该对象将被释放,弱引用现在将指示它引用的对象不再存在。 对对象 obj 的弱引用是通过调用 wr = weakref.ref(obj) 创建的。 被引用的对象是通过调用弱引用返回的,就好像它是一个函数:wr()。 它将返回引用的对象,如果对象不再存在,则返回 None

这使得可以通过在缓存中存储弱引用来编写一个 memoize() 函数,该函数的缓存不会使对象保持活动状态。

_cache = {}
def memoize(x):
    if _cache.has_key(x):
        obj = _cache[x]()
        # If weak reference object still exists,
        # return it
        if obj is not None: return obj

    retval = f(x)

    # Cache a weak reference
    _cache[x] = weakref.ref(retval)

    return retval

weakref 模块还允许创建行为类似于弱引用的代理对象——仅由代理对象引用的对象被释放——但不需要显式调用来检索对象,代理透明地将所有操作转发给只要对象仍然存在。 如果对象被释放,尝试使用代理将导致引发 weakref.ReferenceError 异常。

proxy = weakref.proxy(obj)
proxy.attr   # Equivalent to obj.attr
proxy.meth() # Equivalent to obj.meth()
del obj
proxy.attr   # raises weakref.ReferenceError

也可以看看

PEP 205 - 弱引用
由 Fred L 编写和实施。 德雷克,小


PEP 232:函数属性

在 Python 2.1 中,函数现在可以附加任意信息。 人们经常使用文档字符串来保存有关函数和方法的信息,因为 __doc__ 属性是将任何信息附加到函数的唯一方法。 例如,在 Zope Web 应用程序服务器中,函数通过具有文档字符串被标记为公共访问安全,而在 John Aycock 的 SPARK 解析框架中,文档字符串包含要解析的 BNF 语法的一部分。 这种重载是不幸的,因为文档字符串实际上是用来保存函数的文档的; 例如,这意味着您无法在 Zope 中正确记录供私人使用的功能。

现在可以使用常规 Python 语法在函数上设置和检索任意属性:

def f(): pass

f.publish = 1
f.secure = 1
f.grammar = "A ::= B (C D)*"

包含属性的字典可以作为函数的 __dict__ 访问。 与类实例的 __dict__ 属性不同,在函数中,您实际上可以为 __dict__ 分配一个新字典,尽管新值仅限于常规 Python 字典; 你 不能 很棘手并将其设置为 UserDict 实例,或任何其他行为类似于映射的随机对象。

也可以看看

PEP 232 - 功能属性
由 Barry Warsaw 编写和实施。


PEP 235:在不区分大小写的平台上导入模块

一些操作系统的文件系统不区分大小写,主要的例子是 MacOS 和 Windows; 在这些系统上,不可能区分文件名 FILE.PYfile.py,即使它们确实以原始大小写存储文件名(它们也是大小写保留的)。

在 Python 2.1 中,import 语句将在不区分大小写的平台上模拟区分大小写。 默认情况下,Python 现在将搜索第一个区分大小写的匹配项,如果找不到此类文件,则会引发 ImportError,因此 import file 将不会导入名为 FILE.PY 的模块。 在启动 Python 解释器之前,可以通过设置 PYTHONCASEOK 环境变量来请求不区分大小写的匹配。


PEP 217:交互式显示挂钩

以交互方式使用 Python 解释器时,使用内置的 repr() 函数显示命令的输出。 在 Python 2.1 中,变量 sys.displayhook() 可以设置为一个可调用对象,该对象将被调用而不是 repr()。 例如,您可以将其设置为特殊的漂亮打印功能:

>>> # Create a recursive data structure
... L = [1,2,3]
>>> L.append(L)
>>> L # Show Python's default output
[1, 2, 3, [...]]
>>> # Use pprint.pprint() as the display function
... import sys, pprint
>>> sys.displayhook = pprint.pprint
>>> L
[1, 2, 3,  <Recursion on list with id=135143996>]
>>>

也可以看看

PEP 217 - 用于交互使用的显示挂钩
由 Moshe Zadka 编写和实现。


PEP 208:新的强制模型

显着修改了在 C 级别进行数字强制的方式。 这只会影响 Python 的 C 扩展的作者,让他们在编写支持数字运算的扩展类型时更加灵活。

扩展类型现在可以在它们的 PyTypeObject 结构中设置类型标志 Py_TPFLAGS_CHECKTYPES,以表明它们支持新的强制模型。 在这样的扩展类型中,数字槽函数不能再假设它们将被传递两个相同类型的参数; 相反,它们可以被传递两个不同类型的参数,然后可以执行它们自己的内部强制。 如果槽函数传递了一个它无法处理的类型,它可以通过返回对 Py_NotImplemented 单例值的引用来指示失败。 然后将尝试其他类型的数字函数,也许它们可以处理操作; 如果其他类型也返回 Py_NotImplemented,则会引发 TypeError。 用 Python 编写的数字方法也可以返回 Py_NotImplemented,导致解释器表现为该方法不存在(可能引发 TypeError,可能尝试另一个对象的数字方法)。

也可以看看

PEP 208 - 改造强制模型
由 Neil Schemenauer 编写和实施,主要基于 Marc-André Lemburg 的早期工作。 阅读本文以了解现在如何在 C 级别处理数字运算的要点。


PEP 241:Python 包中的元数据

Python 用户的一个普遍抱怨是,没有一个包含所有 Python 模块的目录。 T。 Middleton's Vaults of Parnassus at http://www.vex.net/parnassus/ 是最大的 Python 模块目录,但是在 Vaults 注册软件是可选的,很多人不会打扰。

作为解决问题的第一步,使用 Distutils sdist 命令打包的 Python 软件将包含一个名为 PKG-INFO 的文件,其中包含有关软件包的信息,例如其名称、版本和作者(元数据,在编目术语中)。 PEP 241 包含可出现在 PKG-INFO 文件中的完整字段列表。 随着人们开始使用 Python 2.1 打包他们的软件,越来越多的包将包含元数据,从而可以构建自动编目系统并对其进行试验。 有了结果经验,也许可以设计一个非常好的目录,然后在 Python 2.2 中构建对它的支持。 例如,Distutils sdistbdist_* 命令可以支持 upload 选项,该选项会自动将您的包上传到目录服务器。

即使您没有使用 Python 2.1,您也可以开始创建包含 PKG-INFO 的包,因为将为早期 Python 版本的用户制作一个新版本的 Distutils。 Distutils 的 1.0.2 版包括 PEP 241 中描述的更改,以及各种错误修复和增强功能。 它将在 https://www.python.org/community/sigs/current/distutils-sig/ 从 Distutils SIG 获得。

也可以看看

PEP 241 - Python 软件包的元数据
由 AM 编写和实施 古奇灵。
PEP 243 - 模块存储库上传机制
该 PEP 草案由 Sean Reifschneider 撰写,描述了一种将 Python 包上传到中央服务器的提议机制。


新的和改进的模块

  • Ka-Ping Yee 贡献了两个新模块:inspect.py,一个用于获取有关实时 Python 代码的信息的模块,以及 pydoc.py,一个用于将文档字符串交互式转换为 HTML 或文本的模块。 作为奖励,现在自动安装的 Tools/scripts/pydoc 使用 pydoc.py 显示给定 Python 模块、包或类名称的文档。 例如,pydoc xml.dom 显示以下内容:

    Python Library Documentation: package xml.dom in xml
    
    NAME
        xml.dom - W3C Document Object Model implementation for Python.
    
    FILE
        /usr/local/lib/python2.1/xml/dom/__init__.pyc
    
    DESCRIPTION
        The Python mapping of the Document Object Model is documented in the
        Python Library Reference in the section on the xml.dom package.
    
        This package contains the following modules:
          ...

    pydoc 还包括一个基于 Tk 的交互式帮助浏览器。 pydoc 很快上瘾; 试试看!

  • 两个不同的单元测试模块被添加到标准库中。 doctest 模块由 Tim Peters 贡献,提供了一个基于在文档字符串中运行嵌入示例并将结果与预期输出进行比较的测试框架。 PyUnit 由 Steve Purcell 贡献,是一个受 JUnit 启发的单元测试框架,而 JUnit 又是对 Kent Beck 的 Smalltalk 测试框架的改编。 有关 PyUnit 的更多信息,请参阅 http://pyunit.sourceforge.net/。

  • difflib 模块包含一个类 SequenceMatcher,它比较两个序列并计算将一个序列转换为另一个序列所需的更改。 例如,这个模块可以用来编写一个类似于Unix diff程序的工具,而实际上示例程序Tools/scripts/ndiff.py演示了如何编写这样的脚本。

  • curses.panel 是面板库的包装器,是 ncurses 和 SYSV 诅咒的一部分,由 Thomas Gellekum 贡献。 面板库为窗口提供了额外的深度功能。 可以在深度排序中将窗口移高或移低,并且面板库会确定面板重叠的位置以及可见的部分。

  • 自 Python 2.0 以来,PyXML 包已经发布了几个版本,Python 2.1 包括 xml 包的更新版本。 一些值得注意的变化包括对 Expat 1.2 及更高版本的支持、Expat 解析器处理 Python 支持的任何编码文件的能力,以及 SAX、DOM 和 minidom 模块的各种错误修复。

  • Ping 还贡献了另一个用于处理未捕获异常的钩子。 sys.excepthook() 可以设置为可调用对象。 当任何 try...except 块没有捕获到异常时,异常将传递给 sys.excepthook(),然后它可以做任何事情喜欢。 在第九届 Python 大会上,Ping 演示了这个钩子的一个应用:打印一个扩展的回溯,不仅列出了堆栈帧,还列出了每个帧的函数参数和局部变量。

  • time 模块中的各种函数,例如 asctime()localtime(),需要一个浮点参数,其中包含自纪元以来的时间(以秒为单位)。 这些函数最常见的用途是处理当前时间,因此浮点参数已成为可选; 当未提供值时,将使用当前时间。 例如,日志文件条目通常需要一个包含当前时间的字符串; 在 Python 2.1 中,可以使用 time.asctime(),而不是以前需要的更长的 time.asctime(time.localtime(time.time()))

    此更改由 Thomas Wouters 提出并实施。

  • ftplib 模块现在默认以被动模式检索文件,因为被动模式更有可能在防火墙后面工作。 这个请求来自 Debian 错误跟踪系统,因为其他 Debian 软件包使用 ftplib 来检索文件,然后不能在防火墙后面工作。 这不太可能对任何人造成问题,因为 Netscape 默认为被动模式,很少有人抱怨,但如果被动模式不适合您的应用程序或网络设置,请在 FTP 对象上调用 set_pasv(0) 以禁用被动模式。

  • socket 模块中添加了对原始套接字访问的支持,由 Grant Edwards 提供。

  • pstats 模块现在包含一个简单的交互式统计浏览器,用于显示 Python 程序的时序配置文件,当模块作为脚本运行时调用。 埃里克 S 供稿 雷蒙德。

  • 添加了一个新的依赖于实现的函数 sys._getframe([depth]),用于从当前调用堆栈返回给定的帧对象。 sys._getframe() 返回调用栈顶部的帧; 如果提供了可选的整数参数 depth,则该函数返回位于堆栈顶部下方的 depth 调用的帧。 例如,sys._getframe(1) 返回调用者的框架对象。

    此函数仅存在于 CPython 中,而不存在于 Jython 或 .NET 实现中。 将其用于调试,并抵制将其放入生产代码的诱惑。


其他更改和修复

由于发布周期较短,Python 2.1 中的较小更改相对较少。 通过 CVS 更改日志搜索发现应用了 117 个补丁,并修复了 136 个错误; 这两个数字都可能被低估。 一些更显着的变化是:

  • 现在可以选择使用专门的对象分配器,它应该比系统 malloc() 更快,并且内存开销更少。 分配器使用 C 的 malloc() 函数来获取大内存池,然后从这些池中满足较小的内存请求。 可以通过向 configure 脚本提供 --with-pymalloc 选项来启用它; 有关实现细节,请参阅 Objects/obmalloc.c

    C 扩展模块的作者应该在启用对象分配器的情况下测试他们的代码,因为一些不正确的代码可能会中断,导致运行时核心转储。 Python 的 C API 中有一堆内存分配函数,它们以前只是 C 库的 malloc()free() 的别名,这意味着如果您不小心调用了不匹配的函数,则错误不会引人注目。 启用对象分配器后,这些函数不再是 malloc()free() 的别名,调用错误的函数来释放内存会导致核心转储。 例如,如果内存是使用 PyMem_New() 分配的,则必须使用 PyMem_Del() 而不是 free() 来释放它。 Python 中包含的一些模块与此冲突,必须修复; 毫无疑问,还有更多的第三方模块会遇到同样的问题。

    对象分配器由 Vladimir Marangozov 贡献。

  • 面向行的文件 I/O 的速度得到了提高,因为人们经常抱怨它的速度不足,而且它经常被用作一个简单的基准测试。 因此,文件对象的 readline() 方法已被重写为更快。 加速的确切数量因平台而异,具体取决于 C 库的 getc() 有多慢,但大约为 66%,并且在某些特定操作系统上可能要快得多。 在 comp.lang.python 中的讨论的推动下,Tim Peters 为这一变化做了很多基准测试和编码。

    还添加了一个用于文件对象的新模块和方法,由 Jeff Epler 贡献。 新方法 xreadlines() 类似于内置的现有 xrange()xreadlines() 返回一个不透明的序列对象,它只支持迭代,在每次迭代时读取一行,而不是像现有的 readlines() 方法那样将整个文件读入内存。 你会像这样使用它:

    for line in sys.stdin.xreadlines():
        # ... do something for each line ...
        ...

    有关线路 I/O 更改的更全面讨论,请参阅 2001 年 1 月 1 日至 15 日的 python-dev 摘要,网址为 https://mail.python.org/pipermail/python-dev/2001-January/[ X164X]。

  • 一个新的方法,popitem(),被添加到字典中,以实现对字典内容的破坏性迭代; 对于大型字典,这会更快,因为无需构建包含所有键或值的列表。 D.popitem() 从字典 D 中删除随机的 (key, value) 对并将其作为 2 元组返回。 这主要是由 Tim Peters 和 Guido van Rossum 在 Moshe Zadka 提出建议和初步补丁后实施的。

  • 模块现在可以通过定义包含将导入的名称列表的 __all__ 属性来控制使用 from module import * 时导入的名称。 一个常见的抱怨是,如果模块导入其他模块,例如 sysstringfrom module import * 会将它们添加到导入模块的命名空间。 要解决此问题,只需列出 __all__ 中的公共名称:

    # List public names
    __all__ = ['Database', 'open']

    本·沃尔夫森 (Ben Wolfson) 首先建议并实施了此补丁的更严格版本,但经过一些 Python 开发讨论后,签入了较弱的最终版本。

  • repr() 应用于先前使用八进制转义的不可打印字符的字符串; 例如,换行符是 '\012'。 这是 Python 的 C 祖先的残余痕迹,但今天八进制几乎没有实际用途。 Ka-Ping Yee 建议使用十六进制转义而不是八进制转义,并使用 \n\t\r 转义适当的字符,并实现了这种新格式。

  • 在编译时检测到的语法错误现在可以引发包含错误文件名和行号的异常,这是 Jeremy Hylton 完成的编译器重组的一个令人愉快的副作用。

  • 导入其他模块的 C 扩展已更改为使用 PyImport_ImportModule(),这意味着它们将使用任何已安装的导入挂钩。 对于需要从 C 代码导入其他模块的第三方扩展,也鼓励这样做。

  • 由于 Fredrik Lundh,Unicode 字符数据库的大小又缩小了 340K。

  • 贡献了一些新的移植:MacOS X(由 Steven Majewski)、Cygwin(由 Jason Tishler); RISCOS(Dietmar Schwertberger); Unixware 7(由 Billy G. 艾莉)。

还有通常的小错误修正、小内存泄漏、文档字符串编辑和其他调整的列表,太长了,不值得一一列举; 如果需要,请参阅 CVS 日志以获取完整的详细信息。


致谢

作者要感谢以下人员对本文的各种草稿提出建议:Graeme Cross、David Goodger、Jay Graves、Michael Hudson、Marc-André Lemburg、Fredrik Lundh、Neil Schemenauer、Thomas Wouters。