Python 2.1 新特性¶
- 作者:
A.M. Kuchling
引言¶
本文介绍了 Python 2.1 中的新功能。虽然 2.1 中的更改不如 Python 2.0 中的多,但仍然有一些令人惊喜的地方。2.1 是第一个通过使用 Python 增强提案(PEP)指导发布的版本,因此大多数重大更改都附有相应的 PEP,这些 PEP 提供了更完整的文档和更改的设计原理。本文并不试图完全记录新功能,而只是为 Python 程序员概述新功能。有关您特别感兴趣的任何新功能的更多详细信息,请参阅 Python 2.1 文档或特定的 PEP。
Python 开发团队最近的一个目标是加快新版本的发布速度,每 6 到 9 个月发布一个新版本。2.1 是第一个以这种更快的速度发布的版本,第一个 alpha 版本在 1 月份出现,即 2.0 的最终版本发布后 3 个月。
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
默认参数现在是不必要的。简而言之,当在函数内没有为给定的变量名赋值(通过赋值或 def
,class
或 import
语句)时,对变量的引用将在封闭作用域的局部命名空间中查找。有关规则的更详细说明以及实现的剖析可以在 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 中,它们默认情况下不启用,但可以通过使用 PEP 236 中描述的 future 语句在模块内启用。(有关 PEP 236 的进一步讨论,请参阅以下部分。)在 Python 2.2 中,嵌套作用域将成为默认设置,并且无法关闭它们,但是用户将有 2.1 的整个生命周期来修复由于引入它们而导致的任何中断。
另请参阅
- PEP 227 - 静态嵌套作用域
由 Jeremy Hylton 编写和实现。
PEP 236:__future__ 指令¶
对嵌套作用域的反应是广泛关注在 2.1 版本中破坏代码的危险,这足以使 Python 开发人员采取更保守的方法。此方法包括引入一种约定,用于在版本 N 中启用可选功能,该功能将在版本 N+1 中强制执行。
该语法使用 from...import
语句,使用保留的模块名称 __future__
。可以通过以下语句启用嵌套作用域
from __future__ import nested_scopes
虽然它看起来像一个普通的 import
语句,但事实并非如此;对于这种 future 语句的放置位置有严格的规则。它们只能位于模块的顶部,并且必须在任何 Python 代码或常规 import
语句之前。这是因为此类语句可能会影响 Python 字节码编译器解析代码和生成字节码的方式,因此它们必须在任何将导致生成字节码的语句之前。
另请参阅
- PEP 236 - 回到
__future__
由 Tim Peters 编写,主要由 Jeremy Hylton 实现。
PEP 207:丰富的比较¶
在早期版本中,Python 对用户自定义类和扩展类型实现比较的支持非常简单。类可以实现一个 __cmp__()
方法,该方法接收类的两个实例,如果它们相等则只能返回 0,如果不相等则返回 +1 或 -1;该方法不能引发异常或返回布尔值以外的任何内容。Numeric Python 的用户经常发现这种模型过于薄弱和限制,因为在数值 Python 用于的数字处理程序中,能够对两个矩阵执行元素级比较,返回一个包含每个元素给定比较结果的矩阵会更有用。如果两个矩阵的大小不同,则比较必须能够引发异常以指示错误。
在 Python 2.1 中,为了支持这种需求,添加了丰富的比较。Python 类现在可以分别重载 <
、<=
、>
、>=
、==
和 !=
操作。新的魔术方法名称是
操作 |
方法名称 |
---|---|
|
|
|
|
|
|
|
|
|
|
|
(这些魔术方法以相应的 Fortran 运算符 .LT.
、.LE.
等命名。数值程序员几乎肯定对这些名称非常熟悉,并且会发现它们很容易记住。)
这些魔术方法中的每一个都采用 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 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/
子目录中的 makefile。这使得构建 Python 更快,也使得破解 Makefile 更清晰和更简单。
另请参阅
- PEP 229 - 使用 Distutils 构建 Python
由 A.M. Kuchling 编写和实现。
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()
返回一个对象或一个占用大量内存的数据结构,这可能会成为问题。
弱引用提供了一种实现缓存的方法,它不会使对象在其生命周期结束后仍然存活。如果一个对象只能通过弱引用访问,则该对象将被释放,并且弱引用将指示它所引用的对象不再存在。通过调用 wr = weakref.ref(obj)
可以创建对对象 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. Drake, Jr. 编写和实现。
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.PY
和 file.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 在 www.vex.net/parnassus/
的 Vaults of Parnassus(于 2009 年 2 月退役,可在互联网档案馆 Wayback Machine 中找到)是最大的 Python 模块目录,但在 Vaults 中注册软件是可选的,许多人没有这样做。
作为解决该问题的第一小步,使用 Distutils sdist 命令打包的 Python 软件将包含一个名为 PKG-INFO
的文件,其中包含有关软件包的信息,例如其名称、版本和作者(在编目术语中称为元数据)。PEP 241 包含 PKG-INFO
文件中可能存在的字段的完整列表。随着人们开始使用 Python 2.1 打包他们的软件,越来越多的软件包将包含元数据,从而可以构建自动化编目系统并进行实验。通过结果经验,也许可以设计一个真正好的目录,然后在 Python 2.2 中构建对其的支持。例如,Distutils sdist 和 bdist_* 命令可以支持 upload
选项,该选项会自动将您的软件包上传到目录服务器。
即使您不使用 Python 2.1,也可以开始创建包含 PKG-INFO
的软件包,因为 Distutils 的新版本将为早期 Python 版本的用户发布。Distutils 的 1.0.2 版本包括 PEP 241 中描述的更改,以及各种错误修复和增强功能。它将可从 Distutils SIG 获得,网址为 https://pythonlang.cn/community/sigs/current/distutils-sig/。
新的和改进的模块¶
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
很快就会让人上瘾;快来试试吧!标准库中添加了两个不同的单元测试模块。Tim Peters 贡献的
doctest
模块提供了一个基于运行文档字符串中的嵌入示例并将结果与预期输出进行比较的测试框架。Steve Purcell 贡献的 PyUnit 是一个受 JUnit 启发而来的单元测试框架,JUnit 又是对 Kent Beck 的 Smalltalk 测试框架的改编。有关 PyUnit 的更多信息,请参阅 https://pyunit.sourceforge.net/。difflib
模块包含一个类SequenceMatcher
,它比较两个序列并计算将一个序列转换为另一个序列所需的更改。例如,此模块可用于编写类似于 Unix diff 程序的工具,实际上,示例程序Tools/scripts/ndiff.py
演示了如何编写这样的脚本。Thomas Gellekum 贡献了
curses.panel
,它是面板库的包装器,是 ncurses 和 SYSV curses 的一部分。面板库为窗口提供了额外的深度功能。窗口可以在深度排序中向上或向下移动,面板库会计算出面板重叠的位置以及哪些部分可见。自 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()
,需要一个浮点数参数,其中包含自 epoch 以来的时间(以秒为单位)。这些函数最常见的用法是处理当前时间,因此浮点数参数已设置为可选;当未提供值时,将使用当前时间。例如,日志文件条目通常需要一个包含当前时间的字符串;在 Python 2.1 中,可以使用time.asctime()
,而不是之前需要的冗长的time.asctime(time.localtime(time.time()))
。此更改由 Thomas Wouters 提出并实施。
ftplib
模块现在默认以被动模式检索文件,因为被动模式更可能在防火墙后面工作。此请求来自 Debian 错误跟踪系统,因为其他 Debian 包使用ftplib
来检索文件,然后在防火墙后面无法工作。认为这不太可能给任何人带来问题,因为 Netscape 默认使用被动模式,而且很少有人抱怨,但是如果被动模式不适合你的应用程序或网络设置,请在 FTP 对象上调用set_pasv(0)
以禁用被动模式。Grant Edwards 贡献的对原始套接字访问的支持已添加到
socket
模块中。当
pstats
模块作为脚本运行时,它现在包含一个简单的交互式统计信息浏览器,用于显示 Python 程序的计时配置文件。由 Eric S. Raymond 贡献。添加了一个新的与实现相关的函数
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%,并且在某些特定的操作系统上可能会更快。Tim Peters 为此更改做了大量的基准测试和编码工作,这源于 comp.lang.python 中的一次讨论。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/。
字典添加了一个新的方法
popitem()
,用于以破坏性方式遍历字典的内容;对于大型字典,这可以更快,因为无需构建包含所有键或值的列表。D.popitem()
从字典D
中删除一个随机的(key, value)
对,并将其作为 2 元组返回。此方法主要由 Tim Peters 和 Guido van Rossum 实现,基于 Moshe Zadka 的建议和初步补丁。模块现在可以通过定义一个包含要导入的名称列表的
__all__
属性,来控制使用from module import *
时导入哪些名称。一个常见的抱怨是,如果模块导入了其他模块(例如sys
或string
),from module import *
会将它们添加到导入模块的命名空间中。要解决此问题,只需在__all__
中列出公共名称即可。# List public names __all__ = ['Database', 'open']
Ben Wolfson 首先提出并实现了此补丁的更严格版本,但在经过一些 python-dev 的讨论后,最终采用了一个较弱的版本。
以前对字符串应用
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. Allie 贡献)。
还有通常的次要错误修复、次要内存泄漏、文档字符串编辑和其他调整列表,由于太长而不值得一一列举;如果需要,请参阅 CVS 日志以获取完整详细信息。
致谢¶
作者要感谢以下人员为本文的各种草稿提供建议:Graeme Cross、David Goodger、Jay Graves、Michael Hudson、Marc-André Lemburg、Fredrik Lundh、Neil Schemenauer、Thomas Wouters。