On this page
Python 2.5 新增Function
Author
- A.M. Kuchling
本文介绍了 Python 2.5 中的新Function。 Python 2.5 的finally版本计划于 2006 年 8 月发布。 PEP 356描述了计划的发布时间表。
Python 2.5 中的更改是语言和库改进的有趣组合。我认为,库增强Function对于 Python 的用户社区而言将更为重要,因为添加了几个广泛使用的软件包。新模块包括用于 XML 处理的 ElementTree(xml.etree
),SQLite 数据库模块(sqlite
)和用于调用 C 函数的ctypes模块。
语言变化具有中等意义。添加了一些令人愉快的新Function,但其中大多数并不是您每天都会使用的Function。最后,使用一种新颖的语法将条件表达式添加到了语言中。参见第PEP 308:条件表达式节。新的'with'语句将使编写清除代码更加容易(第PEP 343:“ with”语句节)。现在可以将值传递到生成器中(PEP 342:Generator 的新Function部分)。导入现在可以显示为绝对或相对(第PEP 328:绝对 import 和相对 import节)。某些异常处理的特殊情况得到了更好的处理(第PEP 341:统一try/exception/finally节)。所有这些改进都是值得的,但是它们是对一种特定语言Function或另一种特定语言Function的改进。它们都不是对 Python 语义的广泛修改。
以及语言和库的添加,在整个源代码树中进行了其他改进和错误修正。在 SVN 更改日志中进行搜索后发现,在 Python 2.4 和 2.5 之间修复了 353 个补丁,并修复了 458 个错误。 (两个数字都可能被低估了.)
本文并不试图成为新Function的完整规范;而是使用有用的示例简要介绍更改。有关完整的详细信息,请始终参阅https://docs.python.org的 Python 2.5 文档。如果您想了解完整的实现和设计原理,请参考 PEP 以获得特定的新Function。
欢迎对此文档提出意见,建议和错误报告;请pass电子邮件将其发送给作者,或在 Python 错误跟踪器中打开错误。
PEP 308:条件表达式
很长时间以来,人们一直在要求一种写条件表达式的方法,条件表达式是根据布尔值是 true 还是 false 来返回值 A 或值 B 的表达式。条件表达式使您可以编写一条具有以下效果的赋值语句:
if condition:
x = true_value
else:
x = false_value
在 python-dev 和 comp.lang.python 上都进行了无休止的语法讨论。甚至举行了投票,发现大多数选民都希望某种形式的条件表达,但没有明显的多数赞成的语法。候选人包括 C 的cond ? true_v : false_v
,if cond then true_v else false_v
和其他 16 个变体。
Guido van Rossum finally选择了一种令人惊讶的语法:
x = true_value if condition else false_value
评估仍然像现有的布尔表达式一样懒惰,因此评估的 Sequences 略有不同。首先评估中间的* condition 表达式,仅在条件为 true 时才评估 true_value 表达式。同样,仅在条件为 false 时才对 false_value *表达式求值。
这种语法可能看起来很奇怪而且倒退。为什么条件出现在表达式的中间而不是 C 的c ? x : y
的最前面?pass将新语法应用于标准库中的模块并查看结果代码的读取方式来检查该决定。在许多使用条件表达式的情况下,一个值似乎是“普通情况”,而一个值是“exceptions”,仅在不满足条件的极少数情况下使用。条件语法使这种模式更加明显:
contents = ((doc + '\n') if doc else '')
我读了上面的语句,意思是“这里的* contents 通常被赋值为doc+'\n'
;有时 doc *是空的,在特殊情况下会返回一个空字符串。”我怀疑在没有明显常见和不常见的情况下,我会经常使用条件表达式。
有人讨论了该语言是否应要求在条件表达式周围加上括号。做出的决定是不需要使用 Python 语言语法中的括号,但是出于风格考虑,我认为您应该始终使用它们。考虑以下两个语句:
# First version -- no parens
level = 1 if logging else 0
# Second version -- with parens
level = (1 if logging else 0)
在第一个版本中,我认为 Reader 可能会将语句分为“ level = 1”,“ if logging”,“ else 0”,并认为条件决定是否执行对* level *的赋值。我认为第二个版本读起来更好,因为它清楚地表明始终执行分配,并且在两个值之间进行选择。
包含方括号的另一个原因:列表理解和 lambda 的一些奇怪组合看起来像是不正确的条件表达式。有关示例,请参见 PEP 308。如果在条件表达式两边加上括号,则不会遇到这种情况。
See also
PEP 308-条件表达式
由 Guido van Rossum 和 Raymond D.Hettinger 撰写的 PEP;由 Thomas Wouters 实施。
PEP 309:部分Function应用
functools模块旨在包含用于Function样式编程的工具。
partial()
Function是此模块中的一个有用工具。对于以Function风格编写的程序,您有时会想要构造已填充一些参数的现有函数的变体。考虑一个 Python 函数f(a, b, c)
;您可以创建一个等效于f(1, b, c)
的新函数g(b, c)
。这称为“部分Function应用程序”。
partial()
接受参数(function, arg1, arg2, ... kwarg1=value1, kwarg2=value2)
。结果对象是可调用的,因此您可以调用它以使用填充的参数调用* function *。
这是一个小而现实的示例:
import functools
def log (message, subsystem):
"Write the contents of 'message' to the specified subsystem."
print '%s: %s' % (subsystem, message)
...
server_log = functools.partial(log, subsystem='server')
server_log('Unable to open socket')
这是另一个使用 PyGTK 的程序的示例。这里,上下文相关的弹出菜单是动态构造的。为菜单选项提供的回调是open_item()
方法的部分应用版本,其中已提供了第一个参数。
...
class Application:
def open_item(self, path):
...
def init (self):
open_func = functools.partial(self.open_item, item_path)
popup_menu.append( ("Open", open_func, 1) )
functools模块中的另一个Function是update_wrapper(wrapper, wrapped)
函数,可帮助您编写行为良好的装饰器。 update_wrapper()
将名称,模块和 docstring 属性复制到包装函数,以便更容易理解包装函数内部的回溯。例如,您可以编写:
def my_decorator(f):
def wrapper(*args, **kwds):
print 'Calling decorated function'
return f(*args, **kwds)
functools.update_wrapper(wrapper, f)
return wrapper
wraps()
是一个装饰器,可以在您自己的装饰器中使用以复制包装的函数的信息。先前示例的替代版本为:
def my_decorator(f):
@functools.wraps(f)
def wrapper(*args, **kwds):
print 'Calling decorated function'
return f(*args, **kwds)
return wrapper
See also
PEP 309-部分函数应用
PEP 由 Peter Harris 提出并撰写;由 Hye-Shik Chang 和 Nick Coghlan 实施,并由 Raymond Hettinger 改编。
PEP 314:Python 软件包 v1.1 的元数据
一些简单的依赖关系支持已添加到 Distutils。 setup()
函数现在具有requires
,provides
和obsoletes
关键字参数。当使用sdist
命令构建源分发时,依赖项信息将记录在PKG-INFO
文件中。
另一个新的关键字参数是download_url
,应将其设置为软件包源代码的 URL。这意味着现在可以在包索引中查找条目,确定包的依赖关系,然后下载所需的包。
VERSION = '1.0'
setup(name='PyPackage',
version=VERSION,
requires=['numarray', 'zlib (>=1.1.4)'],
obsoletes=['OldPackage']
download_url=('http://www.example.com/pypackage/dist/pkg-%s.tar.gz'
% VERSION),
)
Python 软件包索引https://pypi.org的另一个新增强Function是存储软件包的源和二进制 Files。新的 upload Distutils 命令会将软件包上传到存储库。
在上传软件包之前,您必须能够使用 sdist Distutils 命令构建发行版。一旦完成,您可以运行python setup.py upload
将您的软件包添加到 PyPI 存档中。 (可选)您可以pass提供--sign
和--identity
选项对软件包进行 GPG 签名。
包上传由 Martin vonLöwis 和 Richard Jones 实现。
See also
PEP 314-Python 软件包 v1.1 的元数据
PEP 由 A.M.提出并撰写库奇林,理查德·琼斯和弗雷德·德雷克;由 Richard Jones 和 Fred Drake 实施。
PEP 328:绝对 import 和相对 import
PEP 328的最简单部分是在 Python 2.4 中实现的:现在可以使用括号将使用from ... import ...
语句从模块导入的名称括起来,从而更轻松地导入许多不同的名称。
更复杂的部分已在 Python 2.5 中实现:可以将导入模块指定为使用绝对导入或相对于软件包导入。计划是朝着使绝对导入在将来的 Python 版本中成为默认设置的方向 Developing。
假设您有一个像这样的包目录:
pkg/
pkg/__init__.py
pkg/main.py
pkg/string.py
这定义了一个名为pkg
的包,其中包含pkg.main
和pkg.string
子模块。
考虑main.py
模块中的代码。如果执行语句import string
会发生什么?在 Python 2.4 及更早版本中,它将首先在包的目录中执行相对导入,找到pkg/string.py
,将该文件的内容作为pkg.string
模块导入,并且该模块在pkg.main
模块的命名空间中绑定到名称string
。
如果pkg.string
是您想要的,那就很好。但是,如果您想要 Python 的标准string模块怎么办?没有一种干净的方法可以忽略pkg.string
并寻找标准模块。通常,您必须查看sys.modules
的内容,这有点不干净。 Holger Krekel 的py.std
软件包提供了一种整齐的方式来执行从标准库import py; py.std.string.join()
的导入,但是该软件包并非在所有 Python 安装中都可用。
读取依赖于相对导入的代码也不太清楚,因为可能会使 Reader 对打算使用哪个模块string或pkg.string
感到困惑。 Python 用户很快就学会了不要在其包的子模块名称中重复使用标准库模块的名称,但是您无法避免将子模块的名称用于在将来的 Python 版本中添加的新模块。
在 Python 2.5 中,您可以使用from __future__ import absolute_import
指令将import的行为切换为绝对导入。在将来的版本(可能是 Python 2.7)中,此绝对导入行为将成为默认设置。一旦将绝对导入设置为默认设置,import string
将始终找到标准库的版本。建议用户应尽可能多地开始使用绝对导入,因此最好在代码中开始写入from pkg import string
。
在使用from ... import
格式时,可以pass在模块名称中添加前导句号来实现相对导入:
# Import names from pkg.string
from .string import name1, name2
# Import pkg.string
from . import string
这将导入相对于当前软件包的string模块,因此在pkg.main
中将从pkg.string
导入* name1 和 name2 *。其他前导期从当前包的父级开始执行相对导入。例如,A.B.C
模块中的代码可以执行以下操作:
from . import D # Imports A.B.D
from .. import E # Imports A.E
from ..F import G # Imports A.F.G
前导期间不能与 import 语句的import modname
形式一起使用,只能与from ... import
形式一起使用。
See also
PEP 328-导入:多行和绝对/相对
由 Aahz 撰写的 PEP;由 Thomas Wouters 实施。
Holger Krekel 的 py 库,其中包含
py.std
软件包。
PEP 338:将模块作为脚本执行
Python 2.4 中添加的-m开关作为脚本执行模块,获得了更多的Function。现在,该开关不再使用 Python 解释器中的 C 代码实现,而是使用新模块runpy中的实现。
runpy模块实现了更复杂的导入机制,因此现在可以在pychecker.checker
之类的程序包中运行模块。该模块还支持其他导入机制,例如zipimport模块。这意味着您可以将.zip 存档的路径添加到sys.path
,然后使用-m开关执行存档中的代码。
See also
PEP 338-将模块作为脚本执行
PEP 由 Nick Coghlan 编写和实施。
PEP 341:统一try/exception/finally
在 Python 2.5 之前,try语句有两种形式。您可以使用finally块来确保始终执行代码,也可以使用一个或多个except块来捕获特定的异常。您不能同时合并except
块和finally
块,因为为合并后的版本生成正确的字节码很复杂,并且不清楚合并后的语句的语义。
Guido van Rossum 花了一些时间在 Java 上工作,它确实支持将except块和finally块组合在一起,这澄清了该语句的含义。在 Python 2.5 中,您现在可以编写:
try:
block-1 ...
except Exception1:
handler-1 ...
except Exception2:
handler-2 ...
else:
else-block
finally:
final-block
- block-1 中的代码被执行。如果代码引发异常,则测试各种except块:如果异常属于
Exception1
类,则执行 handler-1 ;否则,将执行 handler-1 。否则,如果它属于Exception2
类,则将执行 handler-2 ,依此类推。如果未引发异常,则执行 else-block *。
无论以前发生了什么,一旦代码块完成并处理了所有引发的异常,* final-block 就会执行。即使异常处理程序或 else-block 中发生错误,并且引发了新的异常, final-block *中的代码仍将运行。
See also
PEP 341-统一 try-except 和 try-finally
由 Georg Brandl 撰写的 PEP;由 Thomas Lee 实施。
PEP 342:发生器的新Function
Python 2.5 添加了一种简单的方法将值传递给生成器。如 Python 2.3 中所介绍的,生成器仅产生输出。一旦调用了生成器的代码来创建迭代器,则在恢复执行时将无法将任何新信息传递给函数。有时,传递某些信息的能力将很有用。对此的恶意解决方案包括使生成器的代码查看全局变量,然后更改全局变量的值,或传入一些可变的对象,调用者随后对其进行修改。
为了刷新您对基本生成器的 Memory,这是一个简单的示例:
def counter (maximum):
i = 0
while i < maximum:
yield i
i += 1
当您调用counter(10)
时,结果是一个迭代器,该迭代器返回从 0 到 9 的值。遇到yield语句时,迭代器将返回提供的值并暂停函数的执行,并保留局部变量。在对迭代器的next()方法的以下调用中,执行恢复,在yield
语句之后执行。
在 Python 2.3 中,yield是一条语句;它没有返回任何值。在 2.5 中,yield
现在是一个表达式,返回一个可以分配给变量或以其他方式操作的值:
val = (yield i)
我建议您在对返回值进行处理时,始终在yield表达式两边加上括号,如上例所示。括号并不总是必需的,但是总是添加括号而不是记住何时需要它们会更容易。
( PEP 342解释了确切的规则,即yield-表达式必须始终加括号,除非它出现在赋值右侧的顶级表达式上。这意味着您可以编写val = yield i
,但必须使用括号进行操作时,如val = (yield i) + 12
。)
pass调用send(value)
方法将值发送到生成器中。然后恢复生成器的代码,并且yield表达式返回指定的* value *。如果调用常规next()方法,则yield
返回None。
这是前面的示例,经过修改后可以更改内部计数器的值。
def counter (maximum):
i = 0
while i < maximum:
val = (yield i)
# If value provided, change counter
if val is not None:
i = val
else:
i += 1
这是更改计数器的示例:
>>> it = counter(10)
>>> print it.next()
0
>>> print it.next()
1
>>> print it.send(8)
8
>>> print it.next()
9
>>> print it.next()
Traceback (most recent call last):
File "t.py", line 15, in ?
print it.next()
StopIteration
yield通常会返回None,因此您应始终检查这种情况。除非您确定send()
方法将是用于恢复生成器函数的唯一方法,否则不要在表达式中使用它的值。
除了send()
之外,生成器还有另外两个新方法:
throw(type, value=None, traceback=None)
用于在生成器内部引发异常; yield表达式引发异常,生成器的执行被暂停。close()
在生成器内部引发一个新的GeneratorExit异常以终止迭代。收到此异常后,生成器的代码必须引发GeneratorExit或StopIteration。捕获GeneratorExit异常并返回值是非法的,并且会触发RuntimeError;如果函数引发其他异常,则该异常将传播到调用方。当生成器被垃圾收集时,Python 的垃圾收集器也会调用close()
。
如果您需要在发生GeneratorExit时运行清理代码,建议您使用try: ... finally:
套件,而不要捕获GeneratorExit。
这些变化的累积影响是使生成者从单向信息生产者转变为生产者和 Consumer。
生成器也变为协程,子程序的一种更通用的形式。子例程在一个点进入,而在另一点退出(函数的顶部和一个return语句),但是协程可以在许多不同的点(yield语句)进入,退出和恢复。我们必须找出在 Python 中有效使用协程的模式。
close()
方法的添加具有不明显的副作用。 close()
在生成器被垃圾回收时被调用,因此这意味着生成器的代码在生成器被销毁之前获得了运行的最后机会。最后的机会意味着生成器中的try...finally
语句现在可以保证正常工作; finally子句现在将始终有运行的机会。因此,您删除了不能将yield语句与try...finally
套件混合使用的语法限制。这似乎只是一小部分语言琐事,但实际上必须使用生成器和try...finally
才能实现 PEP 343描述的with语句。我将在下一节中查看此新语句。
此更改的另一个更深奥的效果:以前,生成器的gi_frame
属性始终是框架对象。一旦 Generator 耗尽,现在gi_frame
变为None
成为可能。
See also
PEP 343:“ with”语句
'with'语句阐明了以前使用try...finally
块来确保执行清除代码的代码。在本节中,我将讨论通常使用的语句。在下一节中,我将检查实现细节,并说明如何编写用于此语句的对象。
'with'语句是一个新的控制流结构,其基本结构为:
with expression [as variable]:
with-block
对表达式进行求值,它应产生一个支持上下文 Management 协议的对象(即具有enter()和exit()方法)。
对象的enter()在* with-block 执行之前被调用,因此可以运行设置代码。如果给定,它也可能返回绑定到名称 variable 的值。 (请注意, variable 不是 expression *的结果.)
- with-block *执行完成后,即使该块引发异常,该对象的exit()方法也会被调用,因此可以运行清除代码。
要在 Python 2.5 中启用该语句,您需要在模块中添加以下指令:
from __future__ import with_statement
该语句将始终在 Python 2.6 中启用。
现在,一些标准的 Python 对象支持上下文 Management 协议,并且可以与'with'语句一起使用。文件对象是一个示例:
with open('/etc/passwd', 'r') as f:
for line in f:
print line
... more processing code ...
执行此语句后,即使for循环在代码块途中引发了异常,* f *中的文件对象也将自动关闭。
Note
在这种情况下,* f 与open()创建的对象相同,因为file.__enter__()
返回 self *。
threading模块的锁和条件变量也支持'with'语句:
lock = threading.Lock()
with lock:
# Critical section of code
...
该锁在执行该块之前获取,并在该块完成后始终释放。
decimal模块中新的localcontext()
函数使保存和恢复当前的十进制上下文变得容易,它封装了计算所需的精度和舍入 Feature:
from decimal import Decimal, Context, localcontext
# Displays with default precision of 28 digits
v = Decimal('578')
print v.sqrt()
with localcontext(Context(prec=16)):
# All code in this block uses a precision of 16 digits.
# The original context is restored on exiting the block.
print v.sqrt()
编写上下文 Management 器
在幕后,“ with”语句相当复杂。大多数人只会在与现有对象配合使用时使用“ with
”,并且不需要知道这些详细信息,因此您可以根据需要跳过本节的其余部分。新对象的作者将需要了解底层实现的详细信息,并应 continue 阅读。
上下文 Management 协议的高级解释是:
该表达式将被求值,并应产生一个称为“上下文 Management 器”的对象。上下文 Management 器必须具有enter()和exit()方法。
上下文 Management 器的enter()方法被调用。返回的值分配给* VAR *。如果不存在
'as VAR'
子句,则仅丢弃该值。-
- BLOCK *中的代码被执行。
如果* BLOCK *引发异常,则使用异常详细信息调用
__exit__(type, value, traceback)
,该详细信息与sys.exc_info()返回的值相同。该方法的返回值控制是否重新引发该异常:任何错误值都会重新引发该异常,并且True
将导致抑制该异常。您只会很少想抑制该异常,因为如果您这样做,包含'with'语句的代码的作者将永远不会意识到任何错误。如果* BLOCK 没有引发异常,则仍会调用exit()方法,但 type , value 和 traceback *均为
None
。
让我们考虑一个例子。我不会提供详细的代码,而只会概述支持事务的数据库所必需的方法。
(对于不熟悉数据库术语的人:将对数据库的一组更改分组为一个事务.可以提交事务,这意味着将所有更改都写入数据库,也可以回滚,这意味着将所有更改都丢弃并删除.数据库未更改.有关更多信息,请参见任何数据库教科书.)
假设有一个代表数据库连接的对象。我们的目标是让用户编写如下代码:
db_connection = DatabaseConnection()
with db_connection as cursor:
cursor.execute('insert into ...')
cursor.execute('delete from ...')
# ... more operations ...
如果块中的代码完美运行,则应提交事务;如果有异常,则应回滚事务。这是我假设的DatabaseConnection
的基本界面:
class DatabaseConnection:
# Database interface
def cursor (self):
"Returns a cursor object and starts a new transaction"
def commit (self):
"Commits current transaction"
def rollback (self):
"Rolls back current transaction"
enter()方法非常简单,只需启动一个新事务即可。对于此应用程序,结果光标对象将是有用的结果,因此该方法将返回它。然后,用户可以将as cursor
添加到其“ with”语句中,以将光标绑定到变量名。
class DatabaseConnection:
...
def __enter__ (self):
# Code to start a new transaction
cursor = self.cursor()
return cursor
exit()方法最复杂,因为它是大多数工作要做的地方。该方法必须检查是否发生异常。如果没有异常,则提交事务。如果存在异常,则事务将回滚。
在下面的代码中,执行将在函数末尾结束,并返回默认值None
。 None
为假,因此将自动重新引发异常。如果需要,可以更加明确,并在标记的位置添加return语句。
class DatabaseConnection:
...
def __exit__ (self, type, value, tb):
if tb is None:
# No exception, so commit
self.commit()
else:
# Exception occurred, so rollback.
self.rollback()
# return False
contextlib 模块
新的contextlib模块提供了一些Function和装饰器,这些Function和装饰器对于编写要与'with'语句一起使用的对象很有用。
装饰器称为contextmanager()
,它使您可以编写一个生成器函数,而不用定义一个新类。生成器应恰好产生一个值。直到yield的代码都将作为enter()方法执行,产生的值将是该方法的返回值,该值将绑定到'with'语句的as
子句中的变量(如果有)。 yield之后的代码将在exit()方法中执行。 yield
语句将引发块中引发的任何异常。
上一节中的数据库示例可以使用以下装饰器编写为:
from contextlib import contextmanager
@contextmanager
def db_transaction (connection):
cursor = connection.cursor()
try:
yield cursor
except:
connection.rollback()
raise
else:
connection.commit()
db = DatabaseConnection()
with db_transaction(db) as cursor:
...
contextlib模块还具有nested(mgr1, mgr2, ...)
函数,该函数结合了许多上下文 Management 器,因此您无需编写嵌套的'with'语句。在此示例中,单个“ with
”语句既启动数据库事务并获取线程锁:
lock = threading.Lock()
with nested (db_transaction(db), lock) as (cursor, locked):
...
最后,closing(object)
函数返回* object *,以便可以将其绑定到变量,并在该块的末尾调用object.close
。
import urllib, sys
from contextlib import closing
with closing(urllib.urlopen('http://www.yahoo.com')) as f:
for line in f:
sys.stdout.write(line)
See also
PEP 343-“ with”语句
由 Guido van Rossum 和 Nick Coghlan 撰写的 PEP;由 Mike Bland,Guido van Rossum 和 Neal Norwitz 实施。 PEP 显示为“ with”语句生成的代码,这有助于了解该语句的工作方式。
contextlib模块的文档。
PEP 352:作为新样式类的异常
现在,异常类可以是new-style类,而不仅仅是经典类,并且内置的Exception类和所有标准的内置异常(NameError,ValueError等)现在都是new-style的类。
异常的继承层次结构已重新排列。在 2.5 中,继承关系为:
BaseException # New in Python 2.5
|- KeyboardInterrupt
|- SystemExit
|- Exception
|- (all other current built-in exceptions)
之所以进行这种重新安排,是因为人们经常想捕获所有表明程序错误的异常。 KeyboardInterrupt和SystemExit并不是错误,它们通常代表一个明确的动作,例如用户点击 Control-C 或调用sys.exit()的代码。裸露的except:
将捕获所有异常,因此通常需要列出KeyboardInterrupt和SystemExit以便重新引发它们。通常的模式是:
try:
...
except (KeyboardInterrupt, SystemExit):
raise
except:
# Log error...
# Continue running program...
在 Python 2.5 中,您现在可以编写except Exception
以获得相同的结果,捕获通常指示错误的所有异常,但不包括KeyboardInterrupt和SystemExit。与以前的版本一样,裸except:
仍会捕获所有异常。
Python 3.0 的目标是要求从BaseException或BaseException的某些后代派生的任何类作为异常引发,并且 Python 2.x 系列中的 Future 版本可能会开始强制执行此约束。因此,建议您立即开始使所有异常类都从Exception派生。有人建议应在 Python 3.0 中删除裸露的except:
形式,但 Guido van Rossum 尚未决定是否执行此操作。
如raise "Error occurred"
语句中所述,将字符串作为异常进行引发在 Python 2.5 中已被弃用,并将触发警告。目的是能够在几个发行版中删除字符串 exception Function。
See also
PEP 352-异常所需的超类
由 Brett Cannon 和 Guido van Rossum 撰写的 PEP;由 Brett Cannon 实施。
PEP 353:使用 ssize_t 作为索引类型
使用新的Py_ssize_t
类型定义而不是int
对 Python 的 C API 进行了广泛的更改,将允许解释器在 64 位平台上处理更多数据。此更改不会影响 Python 在 32 位平台上的容量。
Python 解释器的各个部分都使用 C 的int
类型存储大小或计数。例如,列表或 Tuples 中的项目数存储在int
中。大多数 64 位平台的 C 编译器仍然将int
定义为 32 位类型,因此这意味着列表最多只能容纳2**31 - 1
= 2147483647 个项目。 (实际上,64 位 C 编译器可以使用几种不同的编程模型-参见http://www.unix.org/version2/whatsnew/lp64_wp.html进行讨论-但最常用的模型将int
保留为 32 位。)
在 32 位平台上,2147483647 项的限制实际上并不重要,因为在达到长度限制之前,您将耗尽内存。每个列表项都需要一个用于指针的空间,该空间为 4 个字节,外加表示该项目的PyObject的空间。 2147483647 * 4 的字节数已超过 32 位地址空间可以包含的字节数。
但是,可以在 64 位平台上处理那么多内存。该大小的列表的指针仅需要 16 GiB 的空间,因此 Python 程序员可以构造这么大的列表并不是没有道理的。因此,必须将 Python 解释器更改为使用int
以外的其他类型,并且在 64 位平台上这将是 64 位类型。更改将导致 64 位计算机不兼容,因此,现在认为值得进行过渡,而 64 位用户的数量仍然相对较少。 (在 5 或 10 年中,我们可能全部都在 64 位计算机上,这样过渡会更加痛苦.)
此更改对 C 扩展模块的作者影响最大。 Python 字符串和容器类型(例如列表和 Tuples)现在使用Py_ssize_t
来存储其大小。诸如PyList_Size()之类的函数现在返回Py_ssize_t
。因此,扩展模块中的代码可能需要将某些变量更改为Py_ssize_t
。
PyArg_ParseTuple()和Py_BuildValue()函数具有Py_ssize_t
的新转换代码n
。 PyArg_ParseTuple()的s#
和t#
默认仍然输出int
,但是您可以在包含Python.h
之前定义宏PY_SSIZE_T_CLEAN
,以使它们返回Py_ssize_t
。
PEP 353的一节介绍了转换指南,扩展作者应阅读该指南,以了解有关支持 64 位平台的信息。
See also
PEP 353-使用 ssize_t 作为索引类型
PEP 由 Martin vonLöwis 编写和实施。
PEP 357:“ __ index__”方法
NumPy 开发人员遇到的问题只能pass添加新的特殊方法index()来解决。当使用切片符号时,如[start:stop:step]
一样,* start , stop 和 step *索引的值必须全部为整数或长整数。 NumPy 定义了各种专门的整数类型,分别与 8 位,16 位,32 位和 64 位的无符号整数和有符号整数相对应,但是没有办法表明这些类型可用作切片索引。
切片不能只使用现有的int()方法,因为该方法还用于强制转换为整数。如果使用int()进行切片,则浮点数也将成为合法的切片索引,这显然是不受欢迎的行为。
而是添加了一个名为index()的新特殊方法。它不带任何参数,并返回一个整数以提供要使用的切片索引。例如:
class C:
def __index__ (self):
return self.value
返回值必须是 Python 整数或长整数。解释器将检查返回的类型是否正确,如果不满足此要求,则会引发TypeError。
相应的nb_index
插槽已添加到 C 级PyNumberMethods结构,以使 C 扩展实现此协议。 PyNumber_Index(obj)
可以在扩展代码中使用,以调用index()函数并检索其结果。
See also
PEP 357-允许将任何对象用于切片
PEP 由 Travis Oliphant 编写和实施。
其他语言更改
这是 Python 2.5 对核心 Python 语言所做的所有更改。
- dict类型具有一个新的钩子,当字典中不包含键时,该子类可让子类提供默认值。当找不到键时,将调用字典的
__missing__(key)
方法。该钩子用于在collections模块中实现新的defaultdict
类。以下示例定义了一个字典,该字典对于任何丢失的键均返回零:
class zerodict (dict):
def __missing__ (self, key):
return 0
d = zerodict({1:1, 2:2})
print d[1], d[2] # Prints 1, 2
print d[3], d[4] # Prints 0, 0
- 8 位和 Unicode 字符串都具有新的
partition(sep)
和rpartition(sep)
方法,可以简化常见的用例。
find(S)
方法通常用于获取索引,然后使用该索引对字符串进行切片并获得分隔符之前和之后的片段。 partition(sep)
将这种模式压缩为一个方法调用,该方法调用返回一个三 Tuples,其中包含分隔符之前的子字符串,分隔符本身以及分隔符之后的子字符串。如果找不到分隔符,则 Tuples 的第一个元素是整个字符串,其他两个元素为空。 rpartition(sep)
还返回一个三 Tuples,但从字符串末尾开始搜索; r
代表“反向”。
Some examples:
>>> ('http://www.python.org').partition('://')
('http', '://', 'www.python.org')
>>> ('file:/usr/share/doc/index.html').partition('://')
('file:/usr/share/doc/index.html', '', '')
>>> (u'Subject: a quick question').partition(':')
(u'Subject', u':', u' a quick question')
>>> 'www.python.org'.rpartition('.')
('www.python', '.', 'org')
>>> 'www.python.org'.rpartition(':')
('', '', 'www.python.org')
(由雷蒙德·海廷格(Raymond Hettinger)提出建议后,由弗雷德里克·伦德(Fredrik Lundh)实施。)
- 字符串类型的
startswith()
和endswith()
方法现在接受要检查的字符串 Tuples。
def is_image_file (filename):
return filename.endswith(('.gif', '.jpg', '.tiff'))
(由汤姆·林恩(Tom Lynn)提出建议后由乔治·布兰 del(Georg Brandl)实施。)
- min()和max()内置函数获得了
key
关键字参数,类似于sort()
的key
参数。该参数提供一个函数,该函数采用单个参数,并为列表中的每个值调用该函数; min()/max()将返回此函数中具有最小/最大返回值的元素。例如,要查找列表中最长的字符串,可以执行以下操作:
L = ['medium', 'longest', 'short']
# Prints 'longest'
print max(L, key=len)
# Prints 'short', because lexicographically 'short' has the largest value
print max(L)
(由史蒂文·贝萨德和雷蒙德·海廷格贡献.)
两个新的内置函数any()和all()评估迭代器是否包含任何 true 或 false 值。如果迭代器返回的任何值为 true,则any()返回True;否则,返回True。否则将返回False。仅当迭代器返回的所有值均评估为 true 时,all()才返回True。 (由 Guido van Rossum 建议,由 Raymond Hettinger 实施.)
现在,类的hash()方法的结果可以是长整数或正整数。如果返回一个长整数,则使用该值的哈希值。在早期版本中,哈希值必须为正整数,但在 2.5 中,将id()内置函数更改为始终返回非负数,并且用户似乎经常在hash()方法中使用
id(self)
(尽管不建议这样做)。ASCII 现在是模块的默认编码。如果模块包含具有 8 位字符的字符串 Literals,但是没有编码语句,则现在是语法错误。在 Python 2.4 中,这触发了警告,而不是语法错误。有关如何语句模块的编码,请参见 PEP 263。例如,您可以在源文件顶部附近添加如下一行:
# -*- coding: latin1 -*-
- 当您try比较 Unicode 字符串和无法使用默认 ASCII 编码转换为 Unicode 的 8 位字符串时,将触发一个新的警告UnicodeWarning。比较的结果为假:
>>> chr(128) == unichr(128) # Can't convert chr(128) to Unicode
__main__:1: UnicodeWarning: Unicode equal comparison failed
to convert both arguments to Unicode - interpreting them
as being unequal
False
>>> chr(127) == unichr(127) # chr(127) can be converted
True
以前这会引发UnicodeDecodeError异常,但是在 2.5 中,这可能会导致在访问字典时出现令人费解的问题。如果您查找unichr(128)
并将chr(128)
用作键,则会出现UnicodeDecodeError异常。 2.5 中的其他更改导致引发此异常,而不是由实现字典的dictobject.c
中的代码抑制。
为这种比较引发异常是完全正确的,但是更改可能会破坏代码,因此引入了UnicodeWarning。
(由 Marc-AndréLemburg 实施.)
Python 程序员有时会犯的一个错误是忘记在软件包目录中包含
__init__.py
模块。调试此错误可能会造成混淆,并且通常需要使用-v开关运行 Python 来记录所有搜索到的路径。在 Python 2.5 中,当导入将某个目录作为包拾取但未找到__init__.py
时,将触发一个新的ImportWarning警告。默认情况下,忽略此警告;在运行 Python 可执行文件以显示警告消息时提供-Wd选项。 (由 Thomas Wouters 实施.)现在,类定义中的 Base Class 列表可以为空。例如,这现在是合法的:
class C():
pass
(由 Brett Cannon 实施.)
互动翻译的更改
在交互式解释器中,quit
和exit
早已是字符串,因此新用户try退出时会得到一些有用的消息:
>>> quit
'Use Ctrl-D (i.e. EOF) to exit.'
在 Python 2.5 中,quit
和exit
现在是仍会自己生成字符串表示形式但也可调用的对象。现在tryquit()
或exit()
的新手将按预期退出解释器。 (由 Georg Brandl 实施.)
Python 可执行文件现在接受标准的长选项--help和--version;在 Windows 上,它也接受/?选项以显示帮助消息。 (由 Georg Brandl 实施.)
Optimizations
2006 年 5 月 21 日至 28 日在冰岛雷克雅未克举行的 NeedForSpeed sprint 上开发了一些优化方法。该 sprint 专注于 CPython 实现的速度增强,由 EWT LLC 资助,CCP Games 在当地提供支持。以下列表中特别标记了此 sprint 中添加的那些优化。
当它们在 Python 2.4 中引入时,内置的set和frozenset类型是构建在 Python 的字典类型之上的。在 2.5 版中,内部数据结构已针对实现集进行了自定义,结果集使用的内存减少了三分之一,并且速度更快。 (由 Raymond Hettinger 实施.)
某些 Unicode 操作(例如查找子字符串,字符串拆分以及字符 Map 编码和解码)的速度已得到提高。 (在 NeedForSpeed 冲刺中,Fredrik Lundh 和 Andrew Dalke 添加了子字符串搜索和拆分改进.WalterDörwald 和 Martin vonLöwis 改进了字符 Map.)
现在,长数字字符串上的
long(str, base)
函数更快,因为计算出的中间结果更少。峰值用于大约 800-1000 位数字的字符串,其中该Function快 6 倍。 (由艾伦·麦金太尔(Alan McIntyre)贡献,并致力于 NeedForSpeed 冲刺。)现在,将遍历文件与
for line in file
混合并调用文件对象的read()
/readline()/readlines()
方法是非法的。迭代使用内部缓冲区,而read*()
方法不使用该缓冲区。相反,它们将在缓冲区之后返回数据,从而导致数据显示为乱序。现在,混合迭代和这些方法将从read*()
方法中触发ValueError。 (由 Thomas Wouters 实施.)struct模块现在将结构格式字符串编译为内部表示形式并缓存该表示形式,从而使速度提高 20%。 (由 Bob Ippolito 在 NeedForSpeed 冲刺中贡献.)
pass切换到 Python 的分配器函数而不是系统的
malloc()
和free()
,re模块的速度提高了 1%或 2%。 (由 Jack Diederich 在 NeedForSpeed 冲刺中贡献.)代码生成器的窥孔优化器现在可以在表达式中执行简单的常量折叠。如果您编写类似
a = 2+3
的代码,则代码生成器将进行算术运算并生成与a = 5
对应的代码。 (由 Raymond Hettinger 提出并实施.)现在,函数调用更快,因为代码对象现在将最近完成的帧(“僵尸帧”)保留在代码对象的内部字段中,并在下次调用代码对象时重新使用它。 (由 Michael Hudson 制作的原始补丁,由 Armin Rigo 和 Richard Jones 修改;在 NeedForSpeed sprint 上完成.)框架对象也略小,这可以改善缓存的局部性并减少一点内存的使用。 (由 Neal Norwitz 提供.)
Python 的内置异常现在是new-style类,此更改可大大加快实例化的速度。因此,Python 2.5 中的异常处理比 2.4 中的异常处理快 30%。 (由 Richard Jones,Georg Brandl 和 Sean Reifschneider 在 NeedForSpeed 冲刺中贡献.)
现在,导入会缓存try的路径,记录它们是否存在,以便解释器在启动时进行较少的
open()
和stat()
调用。 (由 Martin vonLöwis 和 Georg Brandl 贡献.)
新增,改进和删除的模块
标准库在 Python 2.5 中获得了许多增强和错误修复。这是最值得注意的更改的部分列表,按模块名称的字母 Sequences 排列。请查阅源代码树中的Misc/NEWS
文件以获得更完整的更改列表,或者查看 SVN 日志以获取所有详细信息。
audioop模块现在支持 a-LAW 编码,并且 u-LAW 编码的代码已得到改进。 (由 Lars Immisch 贡献.)
codecs模块获得了对增量编解码器的支持。
codec.lookup()
函数现在返回CodecInfo
实例而不是 Tuples。CodecInfo
实例的行为类似于 4Tuples,以保持向后兼容性,但也具有encode
,decode
,incrementalencoder
,incrementaldecoder
,streamwriter
和streamreader
的属性。增量编解码器可以接收 Importing 并以多个块形式产生输出。输出与将整个 Importing 馈送到非增量编解码器相同。有关详细信息,请参见codecs模块文档。 (由 WalterDörwald 设计和实现.)collections模块获得了一个新类型
defaultdict
,该新类型继承了标准dict类型。新类型的行为几乎像字典一样,但是当不存在键时会构造一个默认值,并自动将其添加到字典中以获取请求的键值。
defaultdict
的构造函数的第一个参数是工厂函数,该函数在每次请求但未找到键时都被调用。此工厂函数不接收任何参数,因此您可以使用内置类型构造函数,例如list()或int()。例如,您可以根据单词的首字母为单词构建索引,如下所示:
words = """Nel mezzo del cammin di nostra vita
mi ritrovai per una selva oscura
che la diritta via era smarrita""".lower().split()
index = defaultdict(list)
for w in words:
init_letter = w[0]
index[init_letter].append(w)
打印index
将产生以下输出:
defaultdict(<type 'list'>, {'c': ['cammin', 'che'], 'e': ['era'],
'd': ['del', 'di', 'diritta'], 'm': ['mezzo', 'mi'],
'l': ['la'], 'o': ['oscura'], 'n': ['nel', 'nostra'],
'p': ['per'], 's': ['selva', 'smarrita'],
'r': ['ritrovai'], 'u': ['una'], 'v': ['vita', 'via']}
(由 Guido van Rossum 提供.)
collections模块提供的
deque
deque 类型现在具有remove(value)
方法,该方法将删除队列中第一次出现的* value *,如果找不到该值,则将引发ValueError。 (由 Raymond Hettinger 提供.)新模块:contextlib模块包含与新的'with'语句一起使用的辅助函数。有关此模块的更多信息,请参见contextlib 模块部分。
新模块:cProfile模块是现有profile模块的 C 实现,其开销要低得多。该模块的界面与profile相同:您运行
cProfile.run('main()')
进行Function分析,可以将配置文件数据保存到文件等。目前尚不清楚是否也用 C 编写但与profile模块不匹配的 Hotshot Profiler 介面,将在 Future 的 Python 版本中 continue 维护。 (由 Armin Rigo 提供.)
而且,用于分析探查器测量的数据的pstats模块现在支持pass向Stats
构造函数提供* stream *参数,将输出定向到任何文件对象。 (由 Skip Montanaro 提供.)
- csv模块以逗号分隔的值格式解析文件,它获得了一些增强Function和许多错误修复。现在,您可以pass调用
csv.field_size_limit(new_limit)
函数来设置字段的最大大小(以字节为单位);Ellipsis* new_limit *参数将返回当前设置的限制。reader
类现在具有line_num
属性,该属性对从源读取的物理行数进行计数。记录可以跨越多个物理行,因此line_num
与读取的记录数不同。
CSV 解析器现在对多行引用字段更加严格。以前,如果一行在带引号的字段中结束但没有换行符终止,则将换行符插入返回的字段中。读取包含字段中回车符的文件时,此行为会导致问题,因此代码已更改为不插入换行符即可返回字段。因此,如果嵌入在字段中的换行很重要,则应以保留换行符的方式将 Importing 分成几行。
(由 Skip Montanaro 和 Andrew McNamara 提供.)
- 现在,datetime模块中的datetime类具有
strptime(string, format)
方法来解析日期字符串,该方法由 Josh Spoerri 提供。它使用与time.strptime()和time.strftime()相同的格式字符:
from datetime import datetime
ts = datetime.strptime('10:13:15 2006-03-07',
'%H:%M:%S %Y-%m-%d')
现在,difflib模块中的
SequenceMatcher.get_matching_blocks()
方法保证返回描述匹配子序列的最小块列表。以前,该算法有时会将匹配元素的块分成两个列表项。 (Tim Peters 的增强.)doctest模块获得了
SKIP
选项,该选项使示例完全无法执行。这用于代码片段,这些代码片段是供 Reader 使用的用法示例,实际上并不是测试用例。
- encoding *参数已添加到
testfile()
函数和DocFileSuite
类中,以指定文件的编码。这使得在文档字符串中包含的测试中更容易使用非 ASCII 字符。 (由 Bjorn Tillenius 贡献.)
email软件包已更新至版本 4.0. (由 Barry Warsaw 贡献.)
fileinput模块变得更加灵活。现在支持 Unicode 文件名,并且在input()函数中添加了默认为
"r"
的* mode 参数,以允许以二进制或universal newlines模式打开文件。另一个新参数 openhook *允许您使用open()以外的函数来打开 Importing 文件。遍历文件集后,FileInput
对象的新fileno()
返回当前打开文件的文件 Descriptors。 (由 Georg Brandl 提供.)在gc模块中,新的
get_count()
函数返回一个三 Tuples,其中包含三代 GC 的当前收集计数。这是垃圾收集器的记帐信息。当这些计数达到指定的阈值时,将进行垃圾收集扫描。现在,现有的gc.collect()函数采用可选的* generation *参数 0、1 或 2 来指定要收集的一代。 (由 Barry Warsaw 贡献.)heapq模块中的
nsmallest()
和nlargest()
函数现在支持key
关键字参数,类似于min()/max()函数和sort()
方法提供的参数。例如:
>>> import heapq
>>> L = ["short", 'medium', 'longest', 'longer still']
>>> heapq.nsmallest(2, L) # Return two lowest elements, lexicographically
['longer still', 'longest']
>>> heapq.nsmallest(2, L, key=len) # Return two shortest elements
['short', 'medium']
(由 Raymond Hettinger 提供.)
- itertools.islice()函数现在接受
None
作为 start 和 step 参数。这使其与切片对象的属性更加兼容,因此您现在可以编写以下内容:
s = slice(5) # Create slice object
itertools.islice(iterable, s.start, s.stop, s.step)
(由 Raymond Hettinger 提供.)
format()函数的* val 参数以前可以是字符串,只要出现的字符数不超过一个%char 即可。现在,该参数必须是一个完全为%char 的说明符,且周围没有文本。还添加了一个可选的 monetary *参数,如果True
,它将使用语言环境的规则来格式化货币,从而在三位数的组之间放置分隔符。
要使用多个%char 指定符格式化字符串,请使用新的format_string()
函数,其Function类似于format(),但还支持将%char 指定符与任意文本混合使用。
还添加了一个新的currency()
函数,该函数根据当前语言环境的设置来格式化数字。
(由 Georg Brandl 贡献.)
- mailbox模块进行了大规模重写,除了读取邮箱之外,还添加了修改邮箱的Function。一组新的类包括
mbox
,MH
和Maildir
用来读取邮箱,并具有add(message)
方法用于添加邮件,remove(key)
用于删除邮件以及lock()
/unlock()
用于锁定/解锁邮箱。下面的示例将 maildir 格式的邮箱转换为 mbox 格式的邮箱:
import mailbox
# 'factory=None' uses email.Message.Message as the class representing
# individual messages.
src = mailbox.Maildir('maildir', factory=None)
dest = mailbox.mbox('/tmp/mbox')
for msg in src:
dest.add(msg)
(由 Gregory K. Johnson 贡献.资金由 Google 的 2005 年代码之夏提供.)
新模块:msilib模块允许创建 Microsoft Installer
.msi
文件和 CAB 文件。还包括一些对读取.msi
数据库的支持。 (由 Martin vonLöwis 提供.)nis模块现在pass向nis.match()和nis.maps()函数提供* domain *参数来支持访问系统默认域以外的域。 (由 Ben Bell 提供.)
operator模块的
itemgetter()
和attrgetter()
函数现在支持多个字段。诸如operator.attrgetter('a', 'b')
之类的调用将返回检索a
和b
属性的函数。将此新Function与sort()
方法的key
参数结合使用,可以轻松地使用多个字段对列表进行排序。 (由 Raymond Hettinger 提供.)optparse模块已更新为 Optik 库的 1.5.1 版本。
OptionParser
类获得了epilog
属性,将在帮助消息后打印的字符串以及destroy()
方法来break对象创建的参考循环。 (由 Greg Ward 提供.)os模块进行了几处更改。
stat_float_times
变量现在默认为 true,这意味着os.stat()现在将以浮点数形式返回时间值。 (这并不一定意味着os.stat()将返回精确到几分之一秒的时间;并非所有系统都支持这种精度。)
已添加名为os.SEEK_SET,os.SEEK_CUR和os.SEEK_END的常量;这些是os.lseek()函数的参数。锁定的两个新常量是os.O_SHLOCK和os.O_EXLOCK。
添加了两个新Functionwait3()
和wait4()
。它们类似于waitpid()
函数,该函数 await 子进程退出并返回进程 ID 及其退出状态的 Tuples,但是wait3()
和wait4()
返回附加信息。 wait3()
不接受进程 ID 作为 Importing,因此它 await 所有子进程退出并返回resource.getrusage()函数返回的三 Tuples* process-id , exit-status , resource-usage * 。 wait4(pid)
确实具有进程 ID。 (由 Chad J. Schroeder 贡献.)
在 FreeBSD 上,os.stat()函数现在返回具有纳秒分辨率的时间,并且返回的对象现在具有st_gen
和st_birthtime
。如果平台支持,则st_flags
属性也可用。 (由 Antti Louko 和 DiegoPettenò贡献.)
pdb模块提供的 Python 调试器现在可以存储到达断点并停止执行时要执行的命令列表。创建断点#1 后,Importing
commands 1
并 Importing 要执行的一系列命令,并以end
结束列表。命令列表可以包括恢复执行的命令,例如continue
或next
。 (由 GrégoireDooms 提供.)pickle和
cPickle
模块不再从reduce()方法接受None
的返回值。该方法必须返回一个参数 Tuples。在 Python 2.4 中不建议使用返回None
的Function,因此可以完成该Function的删除。pkgutil模块包含用于查找包的各种 Util Function,已得到增强,以支持 PEP 302的导入钩子,现在也适用于以 ZIP 格式存档存储的包。 (由 Phillip J. Eby 贡献.)
Marc-AndréLemburg 设计的 pybench 基准套件现已包含在
Tools/pybench
目录中。 pybench 套件是对常用pystone.py
程序的改进,因为 pybench 提供了更详细的解释器速度度量。它对特定的操作(例如函数调用,Tuples 切片,方法查找和数字操作)进行计时,而不是像pystone.py
那样执行许多不同的操作并将结果减少为一个数字。pyexpat
模块现在使用 Expat 解析器的 2.0 版。 (由 Trent Mick 提供.)Queue
模块提供的Queue类获得了两个新方法。join()
阻塞,直到检索到队列中的所有项目并且对项目的所有处理工作都已完成。辅助线程调用另一个新方法task_done()
,以通知已完成对项目的处理。 (由 Raymond Hettinger 提供.)从 python 2.0 开始不推荐使用的旧
regex
和regsub
模块finally被删除。其他已删除的模块:statcache
,tzparse
,whrandom
。还删除了:
lib-old
目录,其中包括诸如dircmp
和ni
之类的古老模块。lib-old
不在默认的sys.path
上,因此,除非您的程序将目录显式添加到sys.path
,否则此删除不应影响您的代码。rlcompleter模块不再依赖于导入readline模块,因此现在可以在非 Unix 平台上使用。 (来自 Robert Kiendl 的补丁.)
现在,
SimpleXMLRPCServer
和DocXMLRPCServer
类具有rpc_paths
属性,该属性将 XML-RPC 操作限制为一组有限的 URL 路径。默认是只允许'/'
和'/RPC2'
。将rpc_paths
设置为None
或将其设置为空 Tuples 将禁用此路径检查。由于 Philippe Biondi 的补丁程序,socket模块现在在 Linux 上支持
AF_NETLINK
套接字。 Netlink 套接字是一种特定于 Linux 的机制,用于在用户空间进程和内核代码之间进行通信。有关它们的介绍性文章位于https://www.linuxjournal.com/article/7356。在 Python 代码中,网络链接地址表示为 2 个整数(pid, group_mask)
的 Tuples。
套接字对象recv_into(buffer)
和recvfrom_into(buffer)
上的两个新方法将接收到的数据存储在支持缓冲区协议的对象中,而不是将数据作为字符串返回。这意味着您可以将数据直接放入数组或内存 Map 文件中。
套接字对象还获得了getfamily()
,gettype()
和getproto()
访问器方法,以检索套接字的族,类型和协议值。
新模块:spwd模块提供用于在支持影子密码的系统上访问影子密码数据库的Function。
struct现在更快,因为它使用
pack()
和unpack()
方法将格式字符串编译成Struct
对象。这类似于re模块允许您创建已编译的正则表达式对象的方式。您仍然可以使用模块级的pack()
和unpack()
函数。他们将创建Struct
对象并对其进行缓存。或者,您可以直接使用Struct
个实例:
s = struct.Struct('ih3s')
data = s.pack(1972, 187, 'abc')
year, number, name = s.unpack(data)
您还可以使用pack_into(buffer, offset, v1, v2, ...)
和unpack_from(buffer, offset)
方法直接在缓冲区对象之间进行数据打包。这使您可以将数据直接存储到阵列或内存 Map 文件中。
(Struct
对象由 Bob Ippolito 在 NeedForSpeed 冲刺中实现.对缓冲对象的支持由 Martin Blais 添加,也是在 NeedForSpeed 冲刺中.)
- 在 2.5 开发过程中,Python 开发人员从 CVS 切换到 Subversion。有关确切的构建版本的信息以
sys.subversion
变量((interpreter-name, branch-name, revision-range)
的 3Tuples)形式提供。例如,在撰写本文时,我的 2.5 副本报告('CPython', 'trunk', '45313:45315')
。
passPy_GetBuildInfo()函数,C 扩展也可以使用此信息,该函数返回如下所示的构建信息字符串:"trunk:45355:45356M, Apr 13 2006, 07:42:19"
。 (由 Barry Warsaw 贡献.)
另一个新函数sys._current_frames()返回所有正在运行的线程的当前堆栈帧,作为字典将线程标识符 Map 到调用该函数时该线程中当前活动的最顶层堆栈帧。 (由蒂姆·彼得斯贡献.)
tarfile模块中的
TarFile
类现在具有extractall()
方法,该方法将存档中的所有成员提取到当前工作目录中。也可以将其他目录设置为提取目标,并仅解压缩存档成员的一个子集。
现在可以使用模式'r|*'
自动检测在流模式下打开的 tarfile 的压缩。 (由 LarsGustäbel 提供.)
现在,使用threading模块可以设置创建新线程时使用的堆栈大小。
stack_size([*size*])
函数返回当前配置的堆栈大小,并提供可选的* size *参数设置一个新值。并非所有平台都支持更改堆栈大小,但是 Windows,POSIX 线程和 OS/2 都可以。 (由安德鲁·麦金太尔贡献.)unicodedata模块已更新为使用 Unicode 字符数据库的 4.1.0 版本。某些规范要求版本 3.2.0,因此仍然可以使用unicodedata.ucd_3_2_0。
新模块:uuid模块根据 RFC 4122生成通用唯一标识符(UUID)。 RFC 定义了几个不同的 UUID 版本,这些版本是从起始字符串,系统属性或完全随机生成的。此模块包含
UUID
类和名为uuid1()
,uuid3()
,uuid4()
和uuid5()
的函数,以生成不同版本的 UUID。 (版本 2 UUID 在 RFC 4122中未指定,并且不受此模块的支持。)
>>> import uuid
>>> # make a UUID based on the host ID and current time
>>> uuid.uuid1()
UUID('a8098c1a-f86e-11da-bd1a-00112444be1e')
>>> # make a UUID using an MD5 hash of a namespace UUID and a name
>>> uuid.uuid3(uuid.NAMESPACE_DNS, 'python.org')
UUID('6fa459ea-ee8a-3ca4-894e-db77e160355e')
>>> # make a random UUID
>>> uuid.uuid4()
UUID('16fd2706-8baf-433b-82eb-8c7fada847da')
>>> # make a UUID using a SHA-1 hash of a namespace UUID and a name
>>> uuid.uuid5(uuid.NAMESPACE_DNS, 'python.org')
UUID('886313e1-3b8a-5372-9b90-0c9aee199e5d')
(由许家平贡献.)
weakref模块的
WeakKeyDictionary
和WeakValueDictionary
类型获得了用于迭代字典中包含的弱引用的新方法。将iterkeyrefs()
和keyrefs()
方法添加到WeakKeyDictionary
,并将itervaluerefs()
和valuerefs()
添加到WeakValueDictionary
。 (由小弗雷德·L·德雷克(Fred L. Drake,Jr.)提供。webbrowser模块获得了许多增强。现在可以用作带有
python -m webbrowser
的脚本,以 URL 作为参数;有许多开关可以控制行为(-n
用于新的浏览器窗口,-t
用于新的选项卡)。添加了新的模块级Functionopen_new()
和open_new_tab()
来支持此Function。模块的open()Function支持附加Function,即* autoraise *参数,该参数会在可能时发出是否升起打开的窗口的 signal。支持的列表中添加了许多其他浏览器,例如 Firefox,Opera,Konqueror 和 elinks。 (由 Oleg Broytmann 和 Georg Brandl 贡献.)xmlrpclib
模块现在支持为 XML-RPC 日期类型返回datetime对象。向loads()
函数或Unmarshaller
类提供use_datetime=True
以启用此Function。 (由 Skip Montanaro 提供.)zipfile模块现在支持该格式的 ZIP64 版本,这意味着.zip 存档现在可以大于 4 GiB,并且可以包含大于 4 GiB 的单个文件。 (由 Ronald Oussoren 提供.)
zlib模块的
Compress
和Decompress
对象现在支持copy()方法,该方法复制对象的内部状态并返回新的Compress
或Decompress
对象。 (由 Chris AtLee 提供.)
ctypes 包
由 Thomas Heller 编写的ctypes软件包已添加到标准库中。 ctypes可让您在共享库或 DLL 中调用任意函数。长期用户可能会记得dl
模块,该模块提供了用于加载共享库并在其中调用函数的Function。 ctypes程序包更高级。
若要加载共享库或 DLL,必须创建CDLL
类的实例,并提供共享库或 DLL 的名称或路径。完成后,您可以pass将任意函数作为CDLL
对象的属性进行访问来调用任意函数。
import ctypes
libc = ctypes.CDLL('libc.so.6')
result = libc.printf("Line of output\n")
提供了各种 C 类型的类型构造函数:c_int()
,c_float()
,c_double()
,c_char_p()
(等效于char *
),依此类推。与 Python 类型不同,C 版本都是可变的。您可以将其分配给value
属性以更改包装值。 Python 整数和字符串将自动转换为相应的 C 类型,但是对于其他类型,您必须调用正确的类型构造函数。 (我的意思是* must (必须);弄错了它通常会导致解释器因分段错误而崩溃。)
当 C 函数将修改内存区域时,不应将c_char_p()
与 Python 字符串一起使用,因为 Python 字符串应该是不可变的。违反此规则将导致令人困惑的错误。当您需要可修改的存储区时,请使用create_string_buffer()
:
s = "this is a string"
buf = ctypes.create_string_buffer(s)
libc.strfry(buf)
假定 C 函数返回整数,但是您可以设置函数对象的restype
属性来更改此值:
>>> libc.atof('2.71828')
-1783957616
>>> libc.atof.restype = ctypes.c_double
>>> libc.atof('2.71828')
2.71828
ctypes还提供了 python C API 的包装,作为ctypes.pythonapi
对象。该对象不会在调用函数之前释放全局解释器锁,因为在调用解释器的代码时必须保持该锁。有一个py_object()
类型的构造函数,它将创建PyObject *指针。一个简单的用法:
import ctypes
d = {}
ctypes.pythonapi.PyObject_SetItem(ctypes.py_object(d),
ctypes.py_object("abc"), ctypes.py_object(1))
# d is now {'abc', 1}.
不要忘记使用py_object()
;如果Ellipsis它,则会导致分段错误。
ctypes已经存在了一段时间,但是人们仍然在编写和分发手工编码的扩展模块,因为您不能依赖ctypes存在。既然ctypes已包含在核心 Python 中,也许开发人员将开始在passctypes而不是扩展模块访问的库上编写 Python 包装。
See also
ctypes 网页,包括教程,参考资料和 FAQ。
ctypes模块的文档。
ElementTree 包
Fredrik Lundh 用于处理 XML 的 ElementTree 库的子集已作为xml.etree
添加到标准库中。可用的模块是 ElementTree 1.2.6 中的ElementTree
,ElementPath
和ElementInclude
。 cElementTree
加速器模块也包括在内。
本节的其余部分将简要概述如何使用 ElementTree。 http://effbot.org/zone/element-index.htm提供了 ElementTree 的完整文档。
ElementTree 将 XML 文档表示为元素节点的树。文档的文本内容存储为的text
和tail
属性(这是 ElementTree 和 Document Object Model 之间的主要区别之一;在 DOM 中,节点的类型很多,包括TextNode
.)
最常用的解析函数是parse()
,它接受字符串(假定包含文件名)或类似文件的对象,并返回ElementTree
实例:
from xml.etree import ElementTree as ET
tree = ET.parse('ex-1.xml')
feed = urllib.urlopen(
'http://planet.python.org/rss10.xml')
tree = ET.parse(feed)
拥有ElementTree
实例后,可以调用其getroot()
方法以获取根Element
节点。
还有一个XML()
函数,该函数采用字符串 Literals 并返回Element
节点(而不是ElementTree
)。此函数提供了一种合并 XML 片段的整洁方式,从而方便了 XML 常量:
svg = ET.XML("""<svg width="10px" version="1.0">
</svg>""")
svg.set('height', '320px')
svg.append(elem1)
每个 XML 元素都支持某些类似于字典的访问方式和某些类似于列表的访问方法。类字典操作用于访问属性值,类列表操作用于访问子节点。
Operation | Result |
---|---|
elem[n] |
返回第 n 个子元素。 |
elem[m:n] |
返回第 m 至第 n 个子元素的列表。 |
len(elem) |
返回子元素的数量。 |
list(elem) |
返回子元素列表。 |
elem.append(elem2) |
将* elem2 *添加为子级。 |
elem.insert(index, elem2) |
在指定位置插入* elem2 *。 |
del elem[n] |
删除第 n 个子元素。 |
elem.keys() |
返回属性名称列表。 |
elem.get(name) |
返回属性* name *的值。 |
elem.set(name, value) |
为属性* name *设置新值。 |
elem.attrib |
检索包含属性的字典。 |
del elem.attrib[name] |
删除属性* name *。 |
Comments 和处理指令也表示为Element
个节点。要检查节点是否为 Comments 或处理指令:
if elem.tag is ET.Comment:
...
elif elem.tag is ET.ProcessingInstruction:
...
要生成 XML 输出,应调用ElementTree.write()
方法。像parse()
一样,它可以采用字符串或类似文件的对象:
# Encoding is US-ASCII
tree.write('output.xml')
# Encoding is UTF-8
f = open('output.xml', 'w')
tree.write(f, encoding='utf-8')
(警告:用于输出的默认编码是 ASCII.对于一般的 XML 工作,其中元素名称可以包含任意 Unicode 字符,ASCII 不是一种非常有用的编码,因为如果元素名称包含任何带有值的字符,它将引发异常.大于 127.因此,最好指定可以处理任何 Unicode 字符的其他编码,例如 UTF-8.)
本部分仅是 ElementTree 接口的部分描述。请阅读软件包的官方文档以了解更多详细信息。
See also
ElementTree 的官方文档。
hashlib 程序包
由 Gregory P. Smith 编写的新的hashlib模块已添加,以替换md5
和sha
模块。 hashlib添加了对其他安全哈希(SHA-224,SHA-256,SHA-384 和 SHA-512)的支持。如果可用,该模块将 OpenSSL 用于算法的快速平台优化实现。
旧的md5
和sha
模块仍然作为 hashlib 的包装器存在,以保持向后兼容性。新模块的界面与旧模块的界面非常接近,但不完全相同。最重要的区别是用于创建新哈希对象的构造函数的名称不同。
# Old versions
h = md5.md5()
h = md5.new()
# New version
h = hashlib.md5()
# Old versions
h = sha.sha()
h = sha.new()
# New version
h = hashlib.sha1()
# Hash that weren't previously available
h = hashlib.sha224()
h = hashlib.sha256()
h = hashlib.sha384()
h = hashlib.sha512()
# Alternative form
h = hashlib.new('md5') # Provide algorithm as a string
创建散列对象后,其方法与以前相同:update(string)
将指定的字符串散列为当前摘要状态,digest()
和hexdigest()
将摘要值作为二进制字符串或十六进制数字字符串返回,而copy()返回新字符串具有相同摘要状态的哈希对象。
See also
hashlib模块的文档。
sqlite3 软件包
pysqlite 模块(http://www.pysqlite.org)是 SQLite 嵌入式数据库的包装,已在包名称sqlite3下添加到标准库中。
SQLite 是一个 C 库,它提供轻量级的基于磁盘的数据库,该数据库不需要单独的服务器进程,并允许使用 SQL 查询语言的非标准变体访问数据库。某些应用程序可以使用 SQLite 进行内部数据存储。也可以使用 SQLite 对应用程序进行原型设计,然后将代码移植到更大的数据库中,例如 PostgreSQL 或 Oracle。
pysqlite 由 GerhardHäring 编写,并提供一个与 PEP 249描述的 DB-API 2.0 规范兼容的 SQL 接口。
如果您自己编译 Python 源代码,请注意,源代码树不包括 SQLite 代码,仅包括包装器模块。在编译 Python 之前,您需要安装 SQLite 库和 Headers,并且在必要的 Headers 可用时,构建过程将编译模块。
要使用该模块,必须首先创建一个代表数据库的Connection
对象。此处的数据将存储在/tmp/example
文件中:
conn = sqlite3.connect('/tmp/example')
您也可以提供特殊名称:memory:
以在 RAM 中创建数据库。
拥有Connection
后,您可以创建Cursor
对象并调用其execute()
方法来执行 SQL 命令:
c = conn.cursor()
# Create table
c.execute('''create table stocks
(date text, trans text, symbol text,
qty real, price real)''')
# Insert a row of data
c.execute("""insert into stocks
values ('2006-01-05','BUY','RHAT',100,35.14)""")
通常,您的 SQL 操作将需要使用 Python 变量中的值。您不应该使用 Python 的字符串操作来汇编查询,因为这样做是不安全的。它使您的程序容易受到 SQL 注入攻击。
而是使用 DB-API 的参数替换。在要使用值的任何地方都放置?
作为占位符,然后提供值的 Tuples 作为游标execute()
方法的第二个参数。 (其他数据库模块可以使用其他占位符,例如%s
或:1
.)例如:
# Never do this -- insecure!
symbol = 'IBM'
c.execute("... where symbol = '%s'" % symbol)
# Do this instead
t = (symbol,)
c.execute('select * from stocks where symbol=?', t)
# Larger example
for t in (('2006-03-28', 'BUY', 'IBM', 1000, 45.00),
('2006-04-05', 'BUY', 'MSOFT', 1000, 72.00),
('2006-04-06', 'SELL', 'IBM', 500, 53.00),
):
c.execute('insert into stocks values (?,?,?,?,?)', t)
要在执行 SELECT 语句后检索数据,可以将游标视为迭代器,可以调用游标的fetchone()
方法来检索单个匹配行,也可以调用fetchall()
来获取匹配行的列表。
本示例使用迭代器形式:
>>> c = conn.cursor()
>>> c.execute('select * from stocks order by price')
>>> for row in c:
... print row
...
(u'2006-01-05', u'BUY', u'RHAT', 100, 35.140000000000001)
(u'2006-03-28', u'BUY', u'IBM', 1000, 45.0)
(u'2006-04-06', u'SELL', u'IBM', 500, 53.0)
(u'2006-04-05', u'BUY', u'MSOFT', 1000, 72.0)
>>>
有关 SQLite 支持的 SQL 方言的更多信息,请参见https://www.sqlite.org。
See also
wsgiref 软件包
Web 服务器网关接口(WSGI)v1.0 定义了 Web 服务器和 Python Web 应用程序之间的标准接口,并在 PEP 333中进行了描述。 wsgiref软件包是 WSGI 规范的参考实现。
该软件包包括一个基本的 HTTP 服务器,它将运行 WSGI 应用程序。该服务器可用于调试,但不适用于生产。设置服务器仅需要几行代码:
from wsgiref import simple_server
wsgi_app = ...
host = ''
port = 8000
httpd = simple_server.make_server(host, port, wsgi_app)
httpd.serve_forever()
See also
WSGI 相关资源的中央网站。
PEP 333-Python Web 服务器网关接口 v1.0
PEP 由 Phillip J. Eby 撰写。
Build 和 C API 的更改
对 Python 的构建过程和 C API 的更改包括:
Python 的源代码树是在 Martin vonLöwis 的监督和完美执行的复杂迁移过程中从 CVS 转换为 Subversion 的。该程序开发为 PEP 347。
Coverity 是一家销售名为预防的源代码分析工具的公司,提供了他们检查 Python 源代码的结果。该分析发现了大约 60 个错误,这些错误已得到快速修复。许多错误都是经常出现在错误处理代码中的问题。有关统计信息,请参见https://scan.coverity.com。
C API 的最大更改来自 PEP 353,它修改了解释器以使用
Py_ssize_t
类型定义而不是int
。有关此更改的讨论,请参见前面的PEP 353:使用 ssize_t 作为索引类型部分。字节码编译器的设计已发生很大变化,不再pass遍历解析树来生成字节码。相反,解析树将转换为抽象语法树(或 AST),并且遍历该抽象语法树以生成字节码。
Python 代码可以使用内置的compile()并将_ast.PyCF_ONLY_AST
作为* flags *参数的值来获取 AST 对象:
from _ast import PyCF_ONLY_AST
ast = compile("""a=0
for i in range(10):
a += i
""", "<string>", 'exec', PyCF_ONLY_AST)
assignment = ast.body[0]
for_loop = ast.body[1]
尚未为 AST 代码编写任何官方文档,但是 PEP 339讨论了该设计。要开始学习代码,请阅读Parser/Python.asdl
中各个 AST 节点的定义。 Python 脚本读取此文件,并在Include/Python-ast.h
中生成一组 C 结构定义。 Include/pythonrun.h
中定义的PyParser_ASTFromString()
和PyParser_ASTFromFile()
以 Python 源作为 Importing,并返回表示内容的 AST 的根。然后,可以passPyAST_Compile()
将 AST 转换为代码对象。有关更多信息,请阅读源代码,然后在 python-dev 上提问。
AST 代码是在 Jeremy Hylton 的 Management 下开发的,由(按字母 Sequences)Brett Cannon,Nick Coghlan,Grant Edwards,John Ehresman,Kurt Kaiser,Neal Norwitz,Tim Peters,Armin Rigo 和 Neil Schemenauer 实施(按字母 Sequences) PyCon 等会议上的许多 AST 冲刺。
- 最初在 PyCon DC 2005 的一次演讲中描述了 Evan Jones 的 obmalloc 补丁。 Python 2.4 在 256K 大小的竞技场中分配了小对象,但从未释放过竞技场。有了这个补丁,Python 将在空的竞技场释放它们。finally结果是,在某些平台上,当您分配许多对象时,删除它们时,Python 的内存使用量实际上可能会下降,并且内存可能会返回给 os。 (由 Evan Jones 实施,并由 Tim Peters 重做.)
请注意,此更改意味着扩展模块在分配内存时必须更加小心。 Python 的 API 具有许多不同的Function来分配内存,这些Function分为多个系列。例如,PyMem_Malloc(),PyMem_Realloc()和PyMem_Free()是分配原始内存的一个族,而PyObject_Malloc(),PyObject_Realloc()和PyObject_Free()是另一个应用于创建 Python 对象的族。
以前,这些不同的系列都简化为平台的malloc()
和free()
Function。这意味着如果您出错了,并使用PyMem()
函数分配了内存,但是使用PyObject()函数释放了内存,则没有关系。随着 2.5 对 obmalloc 的更改,这些系列现在可以做不同的事情,不匹配可能会导致段错误。您应该使用 Python 2.5 仔细测试您的 C 扩展模块。
内置集合类型现在具有官方的 C API。调用PySet_New()和PyFrozenSet_New()创建一个新集合,调用PySet_Add()和PySet_Discard()添加和删除元素,并调用PySet_Contains()和PySet_Size()检查该集合的状态。 (由 Raymond Hettinger 提供.)
现在,C 代码可以pass调用Py_GetBuildInfo()函数来获取有关 Python 解释器确切版本的信息,该函数返回一串构建信息,例如:
"trunk:45355:45356M, Apr 13 2006, 07:42:19"
。 (由 Barry Warsaw 贡献.)可以使用两个新的宏来指示当前文件本地的 C 函数,以便可以使用更快的调用约定。
Py_LOCAL(type)
将函数语句为返回指定* type *的值,并使用快速调用限定符。Py_LOCAL_INLINE(type)
做同样的事情,并且还要求内联函数。如果在包含python.h
之前定义了PY_LOCAL_AGGRESSIVE()
,则为模块启用了一组更积极的优化;您应该对结果进行基准测试,以了解这些优化是否 true 使代码更快。 (由 Fredrik Lundh 在 NeedForSpeed 冲刺中贡献.)PyErr_NewException(name, base, dict)
现在可以接受 Base ClassTuples 作为其* base *参数。 (由 Georg Brandl 贡献.)现在不建议使用_发出警告,而推荐使用
PyErr_WarnEx(category, message, stacklevel)
,该函数使您可以指定将此函数和调用者分隔开的堆栈帧数。 * stacklevel *为 1 是调用PyErr_WarnEx()的函数,2 是其之上的函数,依此类推。 (由 Neal Norwitz 添加.)CPython 解释器仍然是用 C 编写的,但是现在可以使用 C 编译器编译代码而不会出现错误。 (由 Anthony Baxter,Martin vonLöwis 和 Skip Montanaro 实施.)
PyRange_New()
Function已删除。它从未被记录下来,也从未在核心代码中使用过,并且进行错误的错误检查非常危险。万一您的扩展程序正在使用它,您可以用以下内容替换它:
range = PyObject_CallFunction((PyObject*) &PyRange_Type, "lll",
start, stop, step);
Port-Specific Changes
MacOS X(10.3 和更高版本):模块的动态加载现在使用
dlopen()
Function而不是 MacOS 特定的Function。MacOS X:
--enable-universalsdk
开关已添加到 configure 脚本中,该脚本将解释器编译为可以在 PowerPC 和 Intel 处理器上运行的通用二进制文件。 (由 Ronald Oussoren 提供; bpo-2573。)Windows:扩展模块的文件 extensions 不再支持
.dll
。.pyd
现在是唯一要搜索的文件 extensions。
移植到 Python 2.5
本部分列出了先前描述的更改,可能需要更改您的代码:
ASCII 现在是模块的默认编码。如果模块包含具有 8 位字符的字符串 Literals,但是没有编码语句,则现在是语法错误。在 Python 2.4 中,这触发了警告,而不是语法错误。
以前,生成器的
gi_frame
属性始终是框架对象。由于PEP 342:Generator 的新Function部分中所述的 PEP 342更改,因此gi_frame
现在可以是None
。当您try比较 Unicode 字符串和无法使用默认 ASCII 编码转换为 Unicode 的 8 位字符串时,将触发一个新的警告UnicodeWarning。以前,此类比较会引发UnicodeDecodeError异常。
库:csv模块现在对多行引用字段更加严格。如果您的文件包含嵌入在字段中的换行符,则应以保留换行符的方式将 Importing 分成几行。
库:locale模块的format()函数以前将接受任何字符串,只要出现的字符数不超过一个%char 即可。在 Python 2.5 中,参数必须是一个完全%char 的说明符,且没有周围的文本。
库:pickle和
cPickle
模块不再接受reduce()方法的None
返回值;该方法必须返回一个参数 Tuples。这些模块也不再接受不建议使用的* bin *关键字参数。库:
SimpleXMLRPCServer
和DocXMLRPCServer
类现在具有rpc_paths
属性,该属性将 XML-RPC 操作限制为一组有限的 URL 路径;默认是只允许'/'
和'/RPC2'
。将rpc_paths
设置为None
或将其设置为空 Tuples 将禁用此路径检查。C API:现在许多函数使用
Py_ssize_t
而不是int
来允许在 64 位计算机上处理更多数据。扩展代码可能需要进行相同的更改以避免警告并支持 64 位计算机。有关此更改的讨论,请参见前面的PEP 353:使用 ssize_t 作为索引类型部分。C API:obmalloc 的更改意味着您必须注意不要混用
PyMem_*()
和PyObject_*()
系列函数的用法。必须使用相应系列的*_Free()
函数释放分配给一个系列的*_Malloc()
的内存。
Acknowledgements
作者在此感谢以下人士对本文的各种草案提供的建议,更正和帮助:Georg Brandl,Nick Coghlan,Phillip J. Eby,LarsGustäbel,Raymond Hettinger,Ralf W. Grosse-Kunstleve,Kent Johnson,伊恩·洛(Iain Lowe),马丁·冯·洛维斯(Martin vonLöwis),弗雷德里克·伦德(Fredrik Lundh),安德鲁·麦克纳马拉(Andrew McNamara),跳过蒙塔纳罗(Montanaro),古斯塔沃·尼迈耶(Gustavo Niemeyer),保罗·普雷斯科德(Paul Prescod),詹姆斯·普赖尔(James Pryor),迈克·罗夫纳(Mike Rovner),斯科特·魏卡特(Scott Weikart),巴里·华沙,托马斯·沃特斯(Thomas Wouters)。