python 2.3的新功能¶
- 作者
库克林
本文解释了Python2.3中的新特性。python 2.3于2003年7月29日发布。
Python2.3的主要主题是抛光2.2中添加的一些特性,为核心语言添加各种小而有用的增强,并扩展标准库。前一版本中引入的新对象模型得益于18个月的错误修复以及改进了新型类性能的优化工作。添加了一些新的内置函数,例如 sum() 和 enumerate() . 这个 in 运算符现在可用于子字符串搜索(例如 "ab" in "abc" 返回 True )
许多新的库功能包括布尔、集合、堆和日期/时间数据类型、从zip格式存档导入模块的能力、对期待已久的python目录的元数据支持、空闲的更新版本以及用于记录消息、封装文本、分析csv文件、处理命令行选项、使用BerkeleyDB D的模块。ATABASE…新模块和增强模块的列表很长。
本文并不试图提供新特性的完整规范,而是提供一个方便的概述。有关完整的详细信息,您应该参考python 2.3的文档,例如python库参考和python参考手册。如果您想了解完整的实现和设计原理,请参考PEP了解特定的新特性。
PEP218:标准集数据类型¶
新的 sets 模块包含集合数据类型的实现。这个 Set 类用于可变集,可以添加和删除成员的集。这个 ImmutableSet 类用于不能修改的集,以及 ImmutableSet 因此可以用作字典键。集合是建立在字典之上的,因此集合中的元素必须是可hash的。
下面是一个简单的例子:
>>> import sets
>>> S = sets.Set([1,2,3])
>>> S
Set([1, 2, 3])
>>> 1 in S
True
>>> 0 in S
False
>>> S.add(5)
>>> S.remove(3)
>>> S
Set([1, 2, 5])
>>>
集合的并集和交集可以用 union() 和 intersection() 方法;另一种表示法使用位运算符 & 和 | . 可变集也有这些方法的就地版本, union_update() 和 intersection_update() . ::
>>> S1 = sets.Set([1,2,3])
>>> S2 = sets.Set([4,5,6])
>>> S1.union(S2)
Set([1, 2, 3, 4, 5, 6])
>>> S1 | S2 # Alternative notation
Set([1, 2, 3, 4, 5, 6])
>>> S1.intersection(S2)
Set([])
>>> S1 & S2 # Alternative notation
Set([])
>>> S1.union_update(S2)
>>> S1
Set([1, 2, 3, 4, 5, 6])
>>>
也可以取两个集合的对称差。这是联合中不在交集中的所有元素的集合。另一种说法是,对称差分包含恰好在一个集合中的所有元素。同样,还有一个替代符号 (^ )和一个不雅名称的就地版本 symmetric_difference_update() . ::
>>> S1 = sets.Set([1,2,3,4])
>>> S2 = sets.Set([3,4,5,6])
>>> S1.symmetric_difference(S2)
Set([1, 2, 5, 6])
>>> S1 ^ S2
Set([1, 2, 5, 6])
>>>
也有 issubset() 和 issuperset() 用于检查一个集是另一个集的子集还是超集的方法:
>>> S1 = sets.Set([1,2,3])
>>> S2 = sets.Set([2,3])
>>> S2.issubset(S1)
True
>>> S1.issubset(S2)
False
>>> S1.issuperset(S2)
True
>>>
参见
- PEP 218 -添加内置集合对象类型
PEP由格雷格诉威尔逊撰写。由Greg V.Wilson、Alex Martelli和GVR实施。
PEP 255:简单生成器¶
在python 2.2中,生成器作为可选功能添加,由 from __future__ import generators 指令。在2.3中,生成器不再需要特殊启用,现在一直存在;这意味着 yield 现在始终是关键字。本节的其余部分是“What's New in python 2.2”文档中生成器描述的副本;如果在python 2.2出现时将其读回,则可以跳过本节的其余部分。
毫无疑问,您对函数调用在python或c中的工作方式非常熟悉。当您调用一个函数时,它会得到一个私有的命名空间,在其中创建局部变量。当函数达到 return 语句,局部变量将被销毁,结果值将返回给调用方。稍后对同一函数的调用将获得一组新的局部变量。但是,如果局部变量在退出函数时没有被丢弃呢?如果你以后能恢复它停止的功能呢?这就是生成器提供的;它们可以被认为是可恢复的功能。
以下是生成器函数的最简单示例:
def generate_ints(N):
for i in range(N):
yield i
一个新的关键字, yield ,用于生成器。任何包含 yield 语句是一个生成器函数;这是由专门编译函数的Python字节码编译器检测到的。
当调用生成器函数时,它不会返回单个值;而是返回支持迭代器协议的生成器对象。关于执行 yield 语句,生成器输出 i ,类似于 return 语句。两者之间的巨大区别 yield 和A return 声明是在达到 yield 生成器的执行状态被挂起,局部变量被保留。下一次调用生成器时 .next() 方法,函数将在 yield 语句。(由于复杂的原因, yield 语句不允许包含在 try A块 try …… finally 语句;读取 PEP 255 为了充分解释 yield 以及例外情况。)
以下是 generate_ints() 生成器:
>>> gen = generate_ints(3)
>>> gen
<generator object at 0x8117f90>
>>> gen.next()
0
>>> gen.next()
1
>>> gen.next()
2
>>> gen.next()
Traceback (most recent call last):
File "stdin", line 1, in ?
File "stdin", line 2, in generate_ints
StopIteration
你也可以写 for i in generate_ints(5) 或 a,b,c = generate_ints(3) .
在生成器函数内部, return 语句只能在没有值的情况下使用,并指示值的处理结束;之后,生成器无法返回任何其他值。 return 具有值,例如 return 5 ,是生成器函数中的语法错误。生成器结果的结束也可以通过升高来表示。 StopIteration 手动执行,或者只让执行流从函数的底部脱落。
通过编写自己的类并将生成器的所有局部变量存储为实例变量,可以手动实现生成器的效果。例如,返回整数列表可以通过设置 self.count 到0,并拥有 next() 方法增量 self.count 然后把它还给我。然而,对于一个中等复杂的生成器,编写一个相应的类将是非常麻烦的。 Lib/test/test_generators.py 包含许多更有趣的示例。最简单的方法是使用生成器递归地实现树的顺序遍历。::
# A recursive generator that generates Tree leaves in in-order.
def inorder(t):
if t:
for x in inorder(t.left):
yield x
yield t.label
for x in inorder(t.right):
yield x
中的另外两个示例 Lib/test/test_generators.py 为N-Queens问题(将$N$Queens放在$NXN$Chess板上,这样就不会有皇后威胁到其他人)和骑士之旅(一条路线可以让骑士不经过任何广场两次就到达$NXN$ChessBoard的每一个广场)。
生成器的概念来自其他编程语言,特别是icon(https://www.cs.alizarian.edu/icon/),其中生成器的概念是核心。在icon中,每个表达式和函数调用的行为都像一个生成器。https://www.cs.alizarian.edu/icon/docs/ipd266.htm上的“图标编程语言概述”中的一个示例给出了以下情况的概念:
sentence := "Store it in the neighboring harbor"
if (i := find("or", sentence)) > 5 then write(i)
在图标中 find() 函数返回找到子字符串“或”的索引:3、23、33。在 if 语句, i 首先分配的值为3,但3小于5,因此比较失败,图标用第二个值23重试。23大于5,因此比较现在成功,代码将值23打印到屏幕上。
在采用生成器作为中心概念时,python并没有达到图标的水平。生成器被认为是核心Python语言的一部分,但是学习或使用它们并不是强制性的;如果它们不能解决您所遇到的任何问题,请随意忽略它们。与图标相比,python接口的一个新特性是,生成器的状态表示为一个具体的对象(迭代器),可以传递给其他函数或存储在数据结构中。
参见
- PEP 255 -简单生成器
作者:Neil Schemenauer,Tim Peters,Magnus Lie Hetland。主要由Neil Schemenauer和Tim Peters实施,其他修复来自Python实验室的工作人员。
PEP 263:源代码编码¶
现在可以将python源文件声明为处于不同的字符集编码中。编码是通过在源文件的第一行或第二行中包含一个特殊格式的注释来声明的。例如,utf-8文件可以声明为::
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
如果没有这种编码声明,则使用的默认编码是7位ASCII。执行或导入包含8位字符的字符串文本且没有编码声明的模块将导致 DeprecationWarning 由python 2.3发出信号;在2.4中,这是一个语法错误。
编码声明只影响Unicode字符串文字,这些文字将使用指定的编码转换为Unicode。请注意,python标识符仍然局限于ASCII字符,因此不能有使用普通字母数字以外字符的变量名。
参见
- PEP 263 -定义python源代码编码
作者:Marc Andr_Lemburg和Martin von L_wis;由铃木Hisao和Martin von L_wis实施。
PEP 273:从zip存档导入模块¶
新的 zipimport 模块添加了从zip格式存档导入模块的支持。您不需要显式导入模块;如果将zip存档的文件名添加到 sys.path . 例如:
amk@nyman:~/src/python$ unzip -l /tmp/example.zip
Archive: /tmp/example.zip
Length Date Time Name
-------- ---- ---- ----
8467 11-26-02 22:30 jwzthreading.py
-------- -------
8467 1 file
amk@nyman:~/src/python$ ./python
Python 2.3 (#1, Aug 1 2003, 19:54:32)
>>> import sys
>>> sys.path.insert(0, '/tmp/example.zip') # Add .zip file to front of path
>>> import jwzthreading
>>> jwzthreading.__file__
'/tmp/example.zip/jwzthreading.py'
>>>
进入 sys.path 现在可以是zip存档的文件名。zip存档文件可以包含任何类型的文件,但只能包含名为 *.py , *.pyc 或 *.pyo 可以导入。如果存档仅包含 *.py 文件,python不会尝试通过添加相应的 *.pyc 文件,这意味着如果压缩文件不包含 *.pyc 文件,导入可能相当慢。
还可以指定存档中的路径,以仅从子目录导入;例如,路径 /tmp/example.zip/lib/ 只能从 lib/ 存档中的子目录。
参见
- PEP 273 -从zip存档导入模块
作者JamesC.Ahlstrom,他也提供了一个实现。python 2.3遵循中的规范 PEP 273 ,但使用了一个仅由van Rossum编写的实现,该实现使用中描述的导入挂钩 PEP 302 .参见第节 PEP 302:新导入的挂钩 有关新导入挂钩的说明。
PEP 277:Unicode文件名支持Windows NT¶
在Windows NT、2000和XP上,系统将文件名存储为Unicode字符串。传统上,python将文件名表示为字节字符串,这是不够的,因为它使某些文件名不可访问。
python现在允许对所有需要文件名的函数使用任意的unicode字符串(在文件系统的限制范围内),尤其是 open() 内置功能。如果将Unicode字符串传递给 os.listdir() ,python现在返回一个unicode字符串列表。一个新函数, os.getcwdu() ,以unicode字符串形式返回当前目录。
字节字符串仍然作为文件名工作,在Windows上,python将使用 mbcs 编码。
其他系统也允许使用Unicode字符串作为文件名,但在将其传递给系统之前将其转换为字节字符串,这可能导致 UnicodeError 被引发。应用程序可以通过检查来测试是否支持任意Unicode字符串作为文件名 os.path.supports_unicode_filenames ,布尔值。
在MacOS之下, os.listdir() 现在可以返回unicode文件名。
参见
- PEP 277 -支持Windows NT的Unicode文件名
由Neil Hodgson撰写;由Neil Hodgson、Martin von L_wis和Mark Hammond实施。
PEP 278:通用新线支持¶
目前使用的三种主要操作系统是微软Windows、苹果的Macintosh操作系统和各种Unix衍生产品。跨平台工作的一个小问题是,这三个平台都使用不同的字符来标记文本文件中行的结尾。Unix使用换行符(ASCII字符10),MacOS使用回车符(ASCII字符13),Windows使用回车符加换行符的两个字符序列。
现在,python的文件对象可以支持行尾约定,而不是后面跟着运行python的平台的约定。用模式打开文件 'U' 或 'rU' 将打开一个文件以便读取 universal newlines 模式。所有三个行尾约定都将转换为 '\n' 在各种文件方法返回的字符串中,例如 read() 和 readline() .
在导入模块和使用 execfile() 功能。这意味着可以在所有三个操作系统之间共享python模块,而无需转换行尾。
在编译python时,可以通过指定 --without-universal-newlines 运行python时切换 configure 脚本。
参见
- PEP 278 -通用换行支持
由杰克·詹森撰写并实施。
PEP 279:枚举()¶
新的内置功能, enumerate() ,将使某些循环更加清晰。 enumerate(thing) 在哪里 事情 是迭代器或序列,返回将返回的迭代器 (0, thing[0]) , (1, thing[1]) , (2, thing[2]) 等等。
更改列表中每个元素的常见习惯用法如下:
for i in range(len(L)):
item = L[i]
# ... compute some result based on item ...
L[i] = result
这可以用重写 enumerate() AS::
for i, item in enumerate(L):
# ... compute some result based on item ...
L[i] = result
参见
- PEP 279 -enumerate()内置函数
由Raymond D.Hettinger编写并实施。
PEP 282:测井包¶
用于写入日志的标准包, logging ,已添加到python 2.3中。它提供了一种强大而灵活的机制来生成日志输出,然后可以以各种方式对其进行过滤和处理。以标准格式编写的配置文件可用于控制程序的日志记录行为。python包含的处理程序可以将日志记录写入标准错误、文件或套接字、发送到系统日志,甚至通过电子邮件发送到特定地址;当然,也可以编写自己的处理程序类。
这个 Logger 类是主要类。大多数应用程序代码将处理一个或多个 Logger 对象,每个对象由应用程序的特定子系统使用。各 Logger 由名称标识,并使用 . 作为组件分隔符。例如,您可能 Logger 实例命名 server , server.auth 和 server.network .后两个实例如下 server 在层次结构中。这意味着如果你把冗长的 server 或直接 server 消息到另一个处理程序,更改也将应用于记录到 server.auth 和 server.network . 还有根 Logger 那是所有其他伐木工人的父母。
为了简单的使用, logging 包中包含一些始终使用根日志的方便函数:
import logging
logging.debug('Debugging information')
logging.info('Informational message')
logging.warning('Warning:config file %s not found', 'server.conf')
logging.error('Error occurred')
logging.critical('Critical error -- shutting down')
这将产生以下输出:
WARNING:root:Warning:config file server.conf not found
ERROR:root:Error occurred
CRITICAL:root:Critical error -- shutting down
在默认配置中,信息和调试消息被抑制,输出被发送到标准错误。您可以通过调用 setLevel() 根记录器上的方法。
注意 warning() 调用使用字符串格式运算符;用于记录消息的所有函数都采用参数 (msg, arg1, arg2, ...) 并记录由 msg % (arg1, arg2, ...) .
还有一个 exception() 记录最新回溯的函数。如果为关键字参数指定了一个真值,则任何其他函数也将记录回溯。 exc_info . ::
def f():
try: 1/0
except: logging.exception('Problem recorded')
f()
这将产生以下输出:
ERROR:root:Problem recorded
Traceback (most recent call last):
File "t.py", line 6, in f
1/0
ZeroDivisionError: integer division or modulo by zero
稍微高级一点的程序将使用根记录器以外的记录器。这个 getLogger(name) 函数用于获取特定的日志,如果该日志尚不存在,则创建该日志。 getLogger(None) 返回根记录器。::
log = logging.getLogger('server')
...
log.info('Listening on port %i', port)
...
log.critical('Disk full')
...
日志记录通常在层次结构上传播,因此将消息记录到 server.auth 也见 server 和 root 但A Logger 可以通过设置 propagate 属性到 False .
有更多的课程由 logging 可以自定义的包。当A Logger 实例被告知记录消息,它创建一个 LogRecord 发送到任意数量不同的 Handler 实例。日志记录器和处理程序也可以有一个附加的筛选器列表,每个筛选器都可以导致 LogRecord 被忽略或可以在传递记录之前对其进行修改。当它们最终输出时, LogRecord 实例被转换为文本 Formatter 类。所有这些类都可以由您自己的专门编写的类替换。
所有这些功能 logging 包应该为即使是最复杂的应用程序提供足够的灵活性。这只是对其功能的不完整概述,因此请参阅包的参考文档了解所有详细信息。阅读 PEP 282 也会有帮助。
参见
- PEP 282 -测井系统
由Vinay Sajip和Trent Mick编写;由Vinay Sajip实施。
PEP 285:布尔类型¶
在python 2.3中添加了一个布尔类型。两个新常量被添加到 __builtin__ 模块, True 和 False . (True 和 False 常量被添加到python 2.2.1中的内置模块中,但是2.2.1版本只被简单地设置为1和0的整数值,并且不是不同的类型。)
此新类型的类型对象命名为 bool ;它的构造函数获取任何python值并将其转换为 True 或 False . ::
>>> bool(1)
True
>>> bool(0)
False
>>> bool([])
False
>>> bool( (1,) )
True
大多数标准库模块和内置函数都已更改为返回布尔值。::
>>> obj = []
>>> hasattr(obj, 'append')
True
>>> isinstance(obj, list)
True
>>> isinstance(obj, tuple)
False
增加了Python的布尔值,主要目的是使代码更清晰。例如,如果您正在读取函数并遇到语句 return 1 你可能想知道 1 表示布尔真值、索引或系数,该值与其他值相乘。如果声明是 return True 但是,返回值的含义非常清楚。
Python 的胸部 not 为了严格的类型检查而添加。一种非常严格的语言(如pascal)也会阻止您使用布尔值执行算术,并要求 if 语句的计算结果始终为布尔值。python不是那么严格,永远也不会像 PEP 285 明确地说。这意味着您仍然可以在 if 语句,甚至是对列表、元组或某些随机对象进行计算的语句。布尔类型是 int 类,以便使用布尔值的算术仍然有效。::
>>> True + 1
2
>>> False + 1
1
>>> False * 75
0
>>> True * 75
75
总结 True 和 False 在一句话中:它们是拼写整数值1和0的可选方法,唯一的区别是 str() 和 repr() 返回字符串 'True' 和 'False' 而不是 '1' 和 '0' .
参见
- PEP 285 -添加bool类型
由GVR编写并实施。
PEP 293:编解码器错误处理回调¶
将Unicode字符串编码为字节字符串时,可能会遇到不可编码的字符。到目前为止,python允许将错误处理指定为“strict”(引发 UnicodeError )“忽略”(跳过字符)或“替换”(在输出字符串中使用问号),默认行为为“严格”。可能需要指定此类错误的替代处理,例如在转换后的字符串中插入XML字符引用或HTML实体引用。
python现在有了一个灵活的框架来添加不同的处理策略。可以添加新的错误处理程序 codecs.register_error() 然后,编解码器可以使用 codecs.lookup_error() . 已为用C编写的编解码器添加了等效的C API。错误处理程序获取必要的状态信息,例如正在转换的字符串、检测到错误的字符串中的位置以及目标编码。然后,处理程序可以引发异常或返回替换字符串。
另外两个错误处理程序是使用这个框架实现的:“backslashreplace”使用python反斜杠引用来表示不可编码的字符,“xmlcharrefreplace”发出XML字符引用。
参见
- PEP 293 -编解码器错误处理回调
由Walter D_rwald编写并实施。
PEP 301:distuils的包索引和元数据¶
对长期请求的Python目录的支持在2.3中首次出现。
目录的核心是新的distutils register 命令。运行 python setup.py register 将收集描述包的元数据,例如包的名称、版本、维护者、描述和C,并将其发送到中央目录服务器。结果目录可从https://pypi.org获得。
为了使目录更有用,可以选择 分类器 关键字参数已添加到distutils setup() 功能。一览表 Trove -可以提供样式字符串来帮助对软件进行分类。
下面是一个例子 setup.py 使用分类器,编写为与distutils的旧版本兼容:
from distutils import core
kw = {'name': "Quixote",
'version': "0.5.1",
'description': "A highly Pythonic Web application framework",
# ...
}
if (hasattr(core, 'setup_keywords') and
'classifiers' in core.setup_keywords):
kw['classifiers'] = \
['Topic :: Internet :: WWW/HTTP :: Dynamic Content',
'Environment :: No Input/Output (Daemon)',
'Intended Audience :: Developers'],
core.setup(**kw)
可以通过运行获得分类器的完整列表 python setup.py register --list-classifiers .
参见
- PEP 301 -distutils的包索引和元数据
由Richard Jones编写并实施。
PEP 302:新导入的挂钩¶
虽然可以编写自定义导入钩子, ihooks 模块是在python 1.3中引入的,没有人真正类似于它,因为编写新的导入钩子既困难又混乱。有各种各样的替代方案,如 imputil 和 iu 模块,但没有一个模块获得过多的认可,而且没有一个模块可以从C代码中轻松地使用。
PEP 302 借鉴前人的观点,尤其是戈登·麦克米兰的观点 iu 模块。三个新项目添加到 sys 模块:
sys.path_hooks是可调用对象的列表;通常是类。每个可调用项都接受一个包含路径的字符串,并返回一个将处理来自此路径的导入的导入程序对象或引发一个ImportError如果无法处理此路径,则出现异常。sys.path_importer_cache缓存每个路径的导入器对象,因此sys.path_hooks对于每个路径只需要遍历一次。sys.meta_path是将在之前遍历的导入程序对象的列表sys.path检查。此列表最初为空,但用户代码可以向其添加对象。添加到此列表的对象可以导入其他内置和冻结模块。
导入程序对象必须有一个方法, find_module(fullname, path=None) . 全名 将是模块或包名称,例如 string 或 distutils.core . find_module() 必须返回具有单个方法的加载程序对象, load_module(fullname) ,创建并返回相应的模块对象。
因此,python新的导入逻辑的伪代码如下(简化了一点;请参见 PEP 302 详细情况如下):
for mp in sys.meta_path:
loader = mp(fullname)
if loader is not None:
<module> = loader.load_module(fullname)
for path in sys.path:
for hook in sys.path_hooks:
try:
importer = hook(path)
except ImportError:
# ImportError, so try the other path hooks
pass
else:
loader = importer.find_module(fullname)
<module> = loader.load_module(fullname)
# Not found!
raise ImportError
参见
- PEP 302 -新导入挂钩
作者是范·罗森和保罗·摩尔。仅由van Rossum实施。
PEP 305:逗号分隔的文件¶
逗号分隔文件是一种常用于从数据库和电子表格中导出数据的格式。python 2.3为逗号分隔的文件添加了一个解析器。
逗号分隔格式乍一看似乎很简单:
Costs,150,200,3.95
读一行然后调用 line.split(',') :什么更简单?但是,插入可以包含逗号的字符串数据,事情会变得更加复杂:
"Costs",150,200,3.95,"Includes taxes, shipping, and sundry items"
一个丑陋的大正则表达式可以解析这个,但是使用 csv 封装简单得多:
import csv
input = open('datafile', 'rb')
reader = csv.reader(input)
for line in reader:
print line
这个 reader() 函数接受许多不同的选项。字段分隔符不限于逗号,可以更改为任何字符,引号和行尾字符也可以。
可以定义和注册逗号分隔文件的不同方言;目前有两种方言,都由Microsoft Excel使用。单独的 csv.writer 类将从一系列元组或列表中生成逗号分隔的文件,并引用包含分隔符的字符串。
参见
- PEP 305 CSV文件API
由凯文·阿尔蒂斯、戴夫·科尔、安德鲁·麦克纳马拉、斯基普·蒙塔纳罗、克里夫·威尔斯撰写并实施。
PEP 307:pickle增强功能¶
这个 pickle 和 cPickle 在2.3开发周期中,模块受到了一些关注。在2.2中,新风格的类可以毫无困难地被腌制,但它们的腌制不是很紧凑; PEP 307 引用一个简单的例子,其中一个新样式的类导致一个腌制字符串的长度是经典类的三倍。
解决方案是发明一种新的pickle协议。这个 pickle.dumps() 函数长期支持文本或二进制标志。在2.3中,此标志从布尔值重新定义为整数:0是旧的文本模式pickle格式,1是旧的二进制格式,现在2是新的2.3特定格式。一个新常数 pickle.HIGHEST_PROTOCOL ,可用于选择可用的最高级协议。
拆线不再被视为安全操作。2.2的 pickle 提供钩子,以防止不安全的类被拆开(特别是 __safe_for_unpickling__ 属性),但这些代码都没有经过审计,因此在2.3中都被删除了。在任何版本的Python中,都不应取消拾取不受信任的数据。
为了减少新类型类的酸洗开销,使用三种特殊方法添加了自定义酸洗的新接口: __getstate__() , __setstate__() 和 __getnewargs__() . 查阅 PEP 307 对于这些方法的完整语义。
作为进一步压缩pickle的一种方法,现在可以使用整数代码而不是长字符串来标识pickle类。Python软件基金会将维护一个标准化代码列表,也有一系列私人使用的代码。目前没有指定代码。
参见
- PEP 307 -pickle协议的扩展
由Guido van Rossum和Tim Peters编写并实施。
扩展切片¶
自从python 1.4以来,切片语法支持可选的第三个“step”或“step”参数。例如,这些都是合法的python语法: L[1:10:2] , L[:-1:1] , L[::-1] . 这是在numerical python开发人员的请求下添加到python的,后者广泛使用第三个参数。但是,python的内置列表、元组和字符串序列类型从未支持此功能,从而引发了 TypeError 如果你试过的话。迈克尔·哈德森贡献了一个补丁来解决这个缺点。
例如,现在可以轻松地提取具有偶数索引的列表元素:
>>> L = range(10)
>>> L[::2]
[0, 2, 4, 6, 8]
负值还可以按相反的顺序复制同一列表:
>>> L[::-1]
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
这也适用于元组、数组和字符串:
>>> s='abcd'
>>> s[::2]
'ac'
>>> s[::-1]
'dcba'
如果您有一个可变的序列,例如一个列表或数组,您可以分配或删除一个扩展切片,但是在分配给扩展切片和常规切片之间存在一些差异。对常规切片的赋值可用于更改序列的长度::
>>> a = range(3)
>>> a
[0, 1, 2]
>>> a[1:3] = [4, 5, 6]
>>> a
[0, 4, 5, 6]
扩展片不是很灵活。当分配给扩展切片时,语句右侧的列表必须包含与其替换的切片相同数量的项::
>>> a = range(4)
>>> a
[0, 1, 2, 3]
>>> a[::2]
[0, 2]
>>> a[::2] = [0, -1]
>>> a
[0, 1, -1, 3]
>>> a[::2] = [0,1,2]
Traceback (most recent call last):
File "<stdin>", line 1, in ?
ValueError: attempt to assign sequence of size 3 to extended slice of size 2
删除更简单:
>>> a = range(4)
>>> a
[0, 1, 2, 3]
>>> a[::2]
[0, 2]
>>> del a[::2]
>>> a
[1, 3]
现在还可以将切片对象传递给 __getitem__() 内置序列的方法:
>>> range(10).__getitem__(slice(0, 5, 2))
[0, 2, 4]
或者直接在下标中使用slice对象:
>>> range(10)[slice(0, 5, 2)]
[0, 2, 4]
为了简化支持扩展切片的实现序列,切片对象现在有了一个方法 indices(length) 如果给定序列的长度,则返回 (start, stop, step) 可以直接传递到的元组 range() . indices() 以与常规切片一致的方式处理省略和越界索引(这个无害的短语隐藏了一堆混乱的细节!)。该方法的用途如下:
class FakeSeq:
...
def calc_item(self, i):
...
def __getitem__(self, item):
if isinstance(item, slice):
indices = item.indices(len(self))
return FakeSeq([self.calc_item(i) for i in range(*indices)])
else:
return self.calc_item(i)
从这个例子中,您还可以看到 slice 对象现在是切片类型的类型对象,不再是函数。这与python 2.2一致,其中 int , str 等等,也发生了同样的变化。
其他语言更改¶
下面是python 2.3对核心python语言所做的所有更改。
这个
yield语句现在总是一个关键字,如第节所述。 PEP 255:简单生成器 本文件。新的内置功能
enumerate()已添加,如第节所述 PEP 279:枚举() 本文件。两个新常量,
True和False与内置的bool类型,如第节所述 PEP 285:布尔类型 本文件。这个
int()类型构造函数现在将返回一个长整数,而不是引发OverflowError当字符串或浮点数太大而无法放入整数时。这可能导致矛盾的结果isinstance(int(expression), int)是错误的,但这似乎不太可能在实践中引起问题。如第节所述,内置类型现在支持扩展切片语法。 扩展切片 本文件。
新的内置功能,
sum(iterable, start=0),将iterable对象中的数字项相加并返回其和。sum()只接受数字,这意味着您不能使用它来连接一组字符串。(亚历克斯·马泰利供稿)list.insert(pos, value)用于插入 value 在列表的前面 pos 为阴性。行为现在已经被更改为与切片索引一致,所以 pos 是-1,值将插入最后一个元素之前,依此类推。list.index(value),搜索 value 在列表中并返回其索引,现在接受可选 开始 和 stop 将搜索限制在列表的一部分的参数。字典有新的方法,
pop(key[, *default*]),返回对应于 key 并从字典中删除该键/值对。如果字典中不存在请求的密钥, default 如果指定,则返回KeyError如果不是,则引发。::>>> d = {1:2} >>> d {1: 2} >>> d.pop(4) Traceback (most recent call last): File "stdin", line 1, in ? KeyError: 4 >>> d.pop(1) 2 >>> d.pop(1) Traceback (most recent call last): File "stdin", line 1, in ? KeyError: 'pop(): dictionary is empty' >>> d {} >>>
还有一个新的类方法,
dict.fromkeys(iterable, value),使用从提供的迭代器获取的键创建字典 可迭代的 所有值都设置为 value ,默认为None.(补丁由Raymond Hettinger提供。)
此外,
dict()构造函数现在接受关键字参数以简化创建小型字典的过程:>>> dict(red=1, blue=2, green=3, black=4) {'blue': 2, 'black': 4, 'green': 3, 'red': 1}
(仅由范·罗森提供。)
这个
assert语句不再检查__debug__标记,这样您就不能再通过将__debug__. 运行python-O开关仍将生成不执行任何断言的代码。大多数类型对象现在是可调用的,因此您可以使用它们来创建新的对象,如函数、类和模块。(这意味着
new在将来的python版本中,可以不推荐使用module,因为现在可以使用types模块。)例如,可以使用以下代码创建新的模块对象:>>> import types >>> m = types.ModuleType('abc','docstring') >>> m <module 'abc' (built-in)> >>> m.__doc__ 'docstring'
一个新的警告,
PendingDeprecationWarning添加以指示正在被弃用的功能。警告会 not 默认打印。要检查将来是否会弃用的功能,请提供-Walways::PendingDeprecationWarning::在命令行上或使用warnings.filterwarnings().对基于字符串的异常进行反预测的过程,如
raise "Error occurred",已经开始了。引发字符串现在将触发PendingDeprecationWarning.使用
None作为变量名,现在将导致SyntaxWarning警告。在未来的python版本中,None可能最终成为关键字。这个
xreadlines()python 2.1中引入的文件对象方法不再是必需的,因为文件现在表现为自己的迭代器。xreadlines()最初是作为一种快速循环文件中所有行的方法引入的,但是现在您可以简单地编写for line in file_obj. 文件对象还具有新的只读encoding提供文件使用的编码的属性;写入文件的Unicode字符串将使用给定的编码自动转换为字节。新样式类使用的方法解析顺序已经更改,但是只有在继承层次结构非常复杂的情况下才会注意到这一区别。经典类不受此更改的影响。python 2.2最初使用的是类的祖先的拓扑类型,但是2.3现在使用的是本文中描述的c3算法。 "A Monotonic Superclass Linearization for Dylan" . 要理解这种变化的动机,请阅读Michele Simionato的文章。 "Python 2.3 Method Resolution Order" 或者从https://mail.python.org/pipermail/python-dev/2002-10月/029035.html开始阅读python dev上的线程。SamuelePedroni首先指出了问题所在,并通过对c3算法进行编码来实现修复。
python通过在执行n个字节码后在线程之间切换来运行多线程程序。n的默认值已从10个字节码增加到100个字节码,通过减少切换开销来加速单线程应用程序。一些多线程应用程序的响应时间可能较慢,但通过使用将限制设置回一个较低的数字,可以很容易地解决这一问题。
sys.setcheckinterval(N).可以使用新的sys.getcheckinterval()功能。一个微小但深远的变化是,由包含在python中的模块定义的扩展类型的名称现在包含模块和
'.'在类型名称前面。例如,在Python2.2中,如果创建了一个套接字并打印了__class__,您将得到以下输出:>>> s = socket.socket() >>> s.__class__ <type 'socket'>
在2.3中,你会得到:
>>> s.__class__ <type '_socket.socket'>
旧样式类和新样式类之间的一个明显的不兼容性已被删除:现在可以将
__name__和__bases__新样式类的属性。对于可以分配的内容有一些限制__bases__与分配给实例的__class__属性。
字符串更改¶
这个
in运算符现在对字符串的工作方式不同。以前,在评估时X in Y在哪里? X 和 Y 是字符串, X 只能是一个字符。现在改变了; X 可以是任意长度的字符串,并且X in Y将返回True如果 X 是的子字符串 Y . 如果 X 是空字符串,结果总是True. ::>>> 'ab' in 'abcd' True >>> 'ad' in 'abcd' False >>> '' in 'abcd' True
请注意,这并不能告诉您子字符串的起始位置;如果需要该信息,请使用
find()字符串方法。这个
strip(),lstrip()和rstrip()字符串方法现在有一个可选参数,用于指定要除去的字符。默认值仍然是删除所有空白字符::>>> ' abc '.strip() 'abc' >>> '><><abc<><><>'.strip('<>') 'abc' >>> '><><abc<><><>\n'.strip('<>') 'abc<><><>\n' >>> u'\u4000\u4001abc\u4000'.strip(u'\u4000') u'\u4001abc' >>>
(由Simon Brunning建议,Walter D_rwald实施。)
这个
startswith()和endswith()字符串方法现在接受负数 开始 和 end 参数。另一个新的字符串方法是
zfill(),最初是中的函数string模块。zfill()在左边填充一个零的数字字符串,直到它达到指定的宽度。请注意%运营商仍然比zfill(). ::>>> '45'.zfill(4) '0045' >>> '12345'.zfill(4) '12345' >>> 'goofy'.zfill(6) '0goofy'
(由Walter D_rwald提供。)
一个新类型的对象,
basestring,已添加。8位字符串和Unicode字符串都继承自此类型,因此isinstance(obj, basestring)将返回True对于任何类型的字符串。它是一个完全抽象的类型,因此无法创建basestring实例。Interned字符串不再是不朽的,现在将以通常的方式被垃圾收集,而对它们的唯一引用来自Interned字符串的内部字典。(由Oren Tirosh实施)
优化¶
新样式类实例的创建速度快得多;它们现在比经典类快得多!
这个
sort()TimPeters广泛重写了List对象的方法,并且实现速度明显加快。由于Karatsuba乘法的实现,现在大长整数的乘法速度快得多。Karatsuba乘法是一种比O(n)更好扩展的算法。 * n)小学乘法算法要求。(克里斯托弗·A·克雷格的原版补丁,蒂姆·彼得斯的大幅修改。)
这个
SET_LINENO操作码现在不见了。这可能会提供一个小的速度增长,这取决于您的编译器的特性。参见第节 其他更改和修复 更详细的解释。(被迈克尔·哈德森移走。)xrange()对象现在有自己的迭代器,使for i in xrange(n)稍快于for i in range(n). (Raymond Hettinger的补丁)为了提高性能,在不同的热点中进行了一些小的重新排列,例如内嵌一个函数或删除一些代码。(主要由全球价值体系实施,但很多人都做出了单一的改变。)
2.3优化的最终结果是,pystone 2.3运行pystone基准比python 2.2快25%。
新的、改进的和不推荐使用的模块¶
和往常一样,Python的标准库收到了一些增强和错误修复。下面是最显著变化的部分列表,按模块名称的字母顺序排列。查阅 Misc/NEWS 在源代码树中查找更完整的更改列表,或者查看CVS日志以获取所有详细信息。
这个
array模块现在支持使用'u'设置字符格式。阵列现在也支持使用+=赋值运算符添加另一个数组的内容,以及*=用于重复数组的赋值运算符。(贾森·奥伦多夫供稿)这个
bsddb模块已被版本4.1.6的 PyBSDDB 包,为BerkeleyDB库的事务特性提供更完整的接口。模块的旧版本已重命名为
bsddb185并且不再自动生成;您必须编辑Modules/Setup启用它。注意新的bsddb包是为了与旧模块兼容,所以如果发现任何不兼容的地方,一定要将错误归档。当升级到python 2.3时,如果新的解释器是用底层BerkeleyDB库的新版本编译的,那么几乎肯定必须将数据库文件转换为新版本。使用新脚本可以很容易地做到这一点db2pickle.py和pickle2db.py在发行版中可以找到Tools/scripts目录。如果您已经使用了pybsddb包并将其导入为bsddb3,您必须更改import将其导入为的语句bsddb.新的
bz2模块是BZ2数据压缩库的接口。bz2压缩数据通常小于相应的zlib-压缩数据。(古斯塔沃·尼迈耶供稿)一组标准日期/时间类型已添加到新的
datetime模块。有关详细信息,请参阅以下部分。ditudil
Extension类现在支持名为 取决于 用于列出扩展名所依赖的其他源文件。这允许distuils在修改任何依赖文件时重新编译模块。例如,如果sampmodule.c包括头文件sample.h,您将创建Extension这样的对象:ext = Extension("samp", sources=["sampmodule.c"], depends=["sample.h"])
修改
sample.h然后会导致重新编译模块。(杰里米·希尔顿供稿)对distutils的其他细微更改:现在检查
CC,CFLAGS,CPP,LDFLAGS和CPPFLAGS环境变量,用于覆盖Python配置中的设置(由RobertWeber提供)。以前
doctest模块将只搜索公共方法和函数的文档字符串以查找测试用例,但现在它也检查私有方法和函数。这个DocTestSuite()函数创建unittest.TestSuite一组中的对象doctest测验。新的
gc.get_referents(object)函数返回被引用的所有对象的列表 object .这个
getopt模块获得新功能,gnu_getopt(),它支持与现有getopt()功能,但使用GNU风格的扫描模式。现有的getopt()遇到非选项参数后立即停止处理选项,但在GNU样式模式下继续处理,这意味着选项和参数可以混合使用。例如::>>> getopt.getopt(['-f', 'filename', 'output', '-v'], 'f:v') ([('-f', 'filename')], ['output', '-v']) >>> getopt.gnu_getopt(['-f', 'filename', 'output', '-v'], 'f:v') ([('-f', 'filename'), ('-v', '')], ['output'])
(彼得·斯特兰德提供。)
这个
grp,pwd和resource模块现在返回增强的元组:>>> import grp >>> g = grp.getgrnam('amk') >>> g.gr_name, g.gr_gid ('amk', 500)
这个
gzip模块现在可以处理超过2 gib的文件。新的
heapq模块包含堆队列算法的实现。堆是一个类似数组的数据结构,它将项目按部分排序的顺序保存,这样,对于每个索引 k ,heap[k] <= heap[2*k+1]和heap[k] <= heap[2*k+2]. 这使得在保持heap属性为o(lg n)的同时快速删除最小的项并插入新项。(有关优先级队列数据结构的更多信息,请参阅https://xlinux.nist.gov/dads//html/priorityque.html。)这个
heapq模块提供heappush()和heappop()用于添加和删除项的函数,同时在某些其他可变的python序列类型上维护heap属性。下面是一个使用python列表的示例:>>> import heapq >>> heap = [] >>> for item in [3, 7, 5, 11, 1]: ... heapq.heappush(heap, item) ... >>> heap [1, 3, 5, 11, 7] >>> heapq.heappop(heap) 1 >>> heapq.heappop(heap) 3 >>> heap [5, 7, 11]
(由凯文·奥康纳撰稿)
已使用来自idlefork项目(http://idlefork.sourceforge.net)的代码更新了idle集成开发环境。最显著的特点是正在开发的代码现在在子流程中执行,这意味着不再需要手动
reload()操作。Idle的核心代码作为idlelib包裹。这个
imaplib模块现在支持通过SSL的IMAP。(由皮尔斯·劳德和蒂诺·兰格提供。)这个
itertools包含许多与迭代器一起使用的有用函数,这些函数受ML和Haskell语言提供的各种函数的启发。例如,itertools.ifilter(predicate, iterator)返回迭代器中函数所针对的所有元素predicate()返回True和itertools.repeat(obj, N)返回objN 时代。模块中还有许多其他函数;有关详细信息,请参阅包的参考文档。(Raymond Hettinger提供。)中的两个新函数
math模块,degrees(rads)和radians(degs),在弧度和度数之间转换。中的其他功能math模块如math.sin()和math.cos()始终需要以弧度测量的输入值。另外,可选 base 参数已添加到math.log()使计算除e和10. (Raymond Hettinger提供。)几个新的posix函数 (
getpgid(),killpg(),lchown(),loadavg(),major(),makedev(),minor()和mknod())添加到posix构成os模块。(Gustavo Niemeyer、Geert Jansen和Denis S.Otkidach撰稿)在
os模块*stat()函数族现在可以在时间戳中报告一秒钟的分数。这样的时间戳表示为浮点数,类似于time.time().在测试过程中,发现如果时间戳是浮动的,一些应用程序将会中断。为了兼容性,在使用
stat_result时间戳将表示为整数。当使用命名字段(在Python2.2中首次引入的特性)时,时间戳仍然表示为整数,除非os.stat_float_times()调用以启用浮点返回值::>>> os.stat("/tmp").st_mtime 1034791200 >>> os.stat_float_times(True) >>> os.stat("/tmp").st_mtime 1034791200.6335014
在Python2.4中,默认值将更改为始终返回浮动。
应用程序开发人员只有在遇到浮点时间戳或使用tuple api时,才应该启用此功能。如果使用该功能,则应在应用程序级别激活该功能,而不是在每次使用的基础上尝试启用它。
这个
optparse模块包含一个新的命令行参数分析器,该分析器可以将选项值转换为特定的python类型,并将自动生成用法消息。有关详细信息,请参阅以下部分。旧的,从未记录过的
linuxaudiodev模块已被弃用,新版本名为ossaudiodev已添加。该模块被重命名,因为OSS声音驱动程序可以在Linux以外的平台上使用,而且界面也被整理,并以各种方式更新。(由Greg Ward和Nicholas Fitzroy Dale提供。)新的
platform模块包含许多函数,这些函数试图确定正在运行的平台的各种属性。有用于获取体系结构、CPU类型、Windows OS版本甚至Linux分发版本的函数。(Marc Andr_Lemburg提供)由提供的解析器对象
pyexpat模块现在可以选择性地缓冲字符数据,从而减少对字符数据处理程序的调用,从而提高性能。设置分析器对象的buffer_text属性到True将启用缓冲。这个
sample(population, k)函数已添加到random模块。 人口 是序列还是xrange包含总体元素的对象,以及sample()选择 k 不替换所选元素的总体元素。 k 可以是任何价值高达len(population). 例如::>>> days = ['Mo', 'Tu', 'We', 'Th', 'Fr', 'St', 'Sn'] >>> random.sample(days, 3) # Choose 3 elements ['St', 'Sn', 'Th'] >>> random.sample(days, 7) # Choose 7 elements ['Tu', 'Th', 'Mo', 'We', 'St', 'Fr', 'Sn'] >>> random.sample(days, 7) # Choose 7 again ['We', 'Mo', 'Sn', 'Fr', 'Tu', 'St', 'Th'] >>> random.sample(days, 8) # Can't choose eight Traceback (most recent call last): File "<stdin>", line 1, in ? File "random.py", line 414, in sample raise ValueError, "sample larger than population" ValueError: sample larger than population >>> random.sample(xrange(1,10000,2), 10) # Choose ten odd nos. under 10000 [3407, 3805, 1505, 7023, 2401, 2267, 9733, 3151, 8083, 9195]
这个
random模块现在使用了一种新的算法,即用C语言实现的Mersenne Twister,它比以前的算法更快、更广泛地被研究。(所有变更均由Raymond Hettinger提供。)
这个
readline模块还获得了一些新功能:get_history_item(),get_current_history_length()和redisplay().这个
rexec和Bastion模块已被声明为已死,并且尝试导入它们将失败,因为RuntimeError. 新的样式类提供了新的方法来突破由rexec也没有人有兴趣修理它们,也没有时间这么做。如果您的应用程序使用rexec,重写它们以使用其他内容。(坚持使用python 2.2或2.1不会使应用程序更安全,因为
rexec这些版本中的模块。重复:如果你正在使用rexec,立即停止使用。)这个
rotor模块已被弃用,因为它用于加密的算法不被认为是安全的。如果需要加密,请使用单独提供的几个AES Python模块之一。这个
shutil模块获得move(src, dest)将文件或目录递归移动到新位置的函数。对更高级的POSIX信号处理的支持已添加到
signal但后来又被移除了,因为事实证明它不可能跨平台可靠地工作。这个
socket模块现在支持超时。你可以调用给settimeout(t)方法来设置 t 秒。后续的套接字操作所花费的时间超过 t 完成的秒数将中止并引发socket.timeout例外。最初的超时实现是由TimO'Malley实现的。Michael Gilfix将它集成到了Python中
socket模块并引导它通过一个冗长的回顾。代码签入后,guido van rossum重写了部分代码。(这是协作开发过程的一个很好的例子。)在Windows上
socket模块现在提供了安全套接字层(SSL)支持。C的值
PYTHON_API_VERSION宏现在在python级别公开为sys.api_version. 可以通过调用new清除当前异常sys.exc_clear()功能。新的
tarfile模块允许读取和写入 tar -格式化存档文件。(拉尔斯·古斯特·贝尔供稿)新的
textwrap模块包含用于封装包含文本段落的字符串的函数。这个wrap(text, width)函数接受一个字符串并返回一个列表,其中包含拆分为不超过所选宽度的行的文本。这个fill(text, width)函数返回一个字符串,重新格式化以适应不超过所选宽度的行。(你可以猜到,fill()是建在wrap(). 例如::>>> import textwrap >>> paragraph = "Not a whit, we defy augury: ... more text ..." >>> textwrap.wrap(paragraph, 60) ["Not a whit, we defy augury: there's a special providence in", "the fall of a sparrow. If it be now, 'tis not to come; if it", ...] >>> print textwrap.fill(paragraph, 35) Not a whit, we defy augury: there's a special providence in the fall of a sparrow. If it be now, 'tis not to come; if it be not to come, it will be now; if it be not now, yet it will come: the readiness is all. >>>
该模块还包含
TextWrapper类,该类实际上实现了文本封装策略。两者都是TextWrapper类与wrap()和fill()函数支持许多其他关键字参数来微调格式;有关详细信息,请参阅模块的文档。(格雷格·沃德供稿)这个
thread和threading模块现在有伴生模块,dummy_thread和dummy_threading,它提供了thread用于不支持线程的平台的模块接口。其目的是简化线程感知模块(那些 不要 依靠线程运行)将以下代码放在顶部:try: import threading as _threading except ImportError: import dummy_threading as _threading
在这个例子中,
_threading用作模块名称,以明确所使用的模块不一定是实际的threading模块。代码可以调用函数并使用_threading是否支持线程,避免if声明并使代码更加清晰。这个模块不会神奇地使多线程代码在没有线程的情况下运行;等待另一个线程返回或执行某些操作的代码将永远挂起。这个
time模块的strptime()函数一直以来都是一个麻烦,因为它使用平台C库的strptime()实现,不同的平台有时会有奇怪的错误。BrettCannon提供了一个用纯Python编写的可移植实现,它在所有平台上的行为都应该相同。新的
timeit模块帮助测量执行python代码片段需要多长时间。这个timeit.py文件可以直接从命令行或模块的Timer类可以直接导入和使用。下面是一个简短的示例,通过向8位字符串追加空的Unicode字符串或使用unicode()功能:import timeit timer1 = timeit.Timer('unicode("abc")') timer2 = timeit.Timer('"abc" + u""') # Run three trials print timer1.repeat(repeat=3, number=100000) print timer2.repeat(repeat=3, number=100000) # On my laptop this outputs: # [0.36831796169281006, 0.37441694736480713, 0.35304892063140869] # [0.17574405670166016, 0.18193507194519043, 0.17565798759460449]
这个
Tix模块已经收到了TIX包当前版本的各种错误修复和更新。这个
Tkinter模块现在使用一个线程支持的TCL版本。TCL的线程模型要求只能从创建它们的线程访问小部件;从另一个线程访问小部件会导致TCL恐慌。对于某些TCL接口,Tkinter当一个小部件从另一个线程访问时,通过整理命令、将其传递到正确的线程并等待结果,现在将自动避免这种情况。其他接口不能自动处理,但是Tkinter现在将对此类访问引发异常,这样您至少可以找到有关问题的信息。有关此更改的详细说明,请参阅https://mail.python.org/pipermail/python-dev/2002-december/031107.html。(由Martin von L_wis实施。)通过调用tcl方法
_tkinter不再只返回字符串。相反,如果tcl返回其他对象,则这些对象将转换为它们的python等效对象(如果存在),或者用_tkinter.Tcl_Obj对象,如果不存在等效的python。这种行为可以通过wantobjects()方法tkapp物体。使用时
_tkinter通过Tkinter模块(与大多数Tkinter应用程序一样),此功能始终处于激活状态。它不应该导致兼容性问题,因为Tkinter总是在可能的情况下将字符串结果转换为python类型。如果发现任何不兼容,可以通过设置
wantobjects中的变量Tkinter在创建第一个模块之前将模块设置为falsetkapp对象。::import Tkinter Tkinter.wantobjects = 0
任何由此变化引起的破损都应作为缺陷报告。
这个
UserDict模块有一个新的DictMixin类,该类为已具有最小映射接口的类定义所有字典方法。这大大简化了编写需要替换字典的类的过程,例如shelve模块。当类定义时,将mix-in作为超类添加将提供完整的字典接口。
__getitem__(),__setitem__(),__delitem__()和keys(). 例如::>>> import UserDict >>> class SeqDict(UserDict.DictMixin): ... """Dictionary lookalike implemented with lists.""" ... def __init__(self): ... self.keylist = [] ... self.valuelist = [] ... def __getitem__(self, key): ... try: ... i = self.keylist.index(key) ... except ValueError: ... raise KeyError ... return self.valuelist[i] ... def __setitem__(self, key, value): ... try: ... i = self.keylist.index(key) ... self.valuelist[i] = value ... except ValueError: ... self.keylist.append(key) ... self.valuelist.append(value) ... def __delitem__(self, key): ... try: ... i = self.keylist.index(key) ... except ValueError: ... raise KeyError ... self.keylist.pop(i) ... self.valuelist.pop(i) ... def keys(self): ... return list(self.keylist) ... >>> s = SeqDict() >>> dir(s) # See that other dictionary methods are implemented ['__cmp__', '__contains__', '__delitem__', '__doc__', '__getitem__', '__init__', '__iter__', '__len__', '__module__', '__repr__', '__setitem__', 'clear', 'get', 'has_key', 'items', 'iteritems', 'iterkeys', 'itervalues', 'keylist', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'valuelist', 'values']
(Raymond Hettinger提供。)
中的DOM实现
xml.dom.minidom现在可以通过向toxml()和toprettyxml()DOM节点的方法。这个
xmlrpclib模块现在支持XML-RPC扩展来处理nil数据值,如pythonNone. 在解组XML-RPC响应时始终支持nil值。生成包含None,必须为 allow_none 创建时的参数Marshaller实例。新的
DocXMLRPCServer模块允许编写自文档化的XML-RPC服务器。在演示模式下运行(作为一个程序)以查看它的运行情况。将Web浏览器指向rpc服务器会生成pydoc样式的文档;将xmlrpclib指向服务器允许调用实际方法。(布莱恩·昆兰供稿)增加了对国际化域名(RFC3454、3490、3491和3492)的支持。“idna”编码可用于在Unicode域名和该名称的ASCII兼容编码(ace)之间进行转换。::
>{}>{}> u"www.Alliancefrançaise.nu".encode("idna") 'www.xn--alliancefranaise-npb.nu'
这个
socket模块还被扩展为在将unicode主机名传递到C库之前将其透明地转换为ace版本。处理主机名的模块,如httplib和ftplib)还支持Unicode主机名;httplib还发送HTTPHost使用域名的ace版本的头。urllib支持具有非ASCII主机名的Unicode URL,只要pathURL的一部分仅为ASCII。要实现此更改,请
stringprep模块mkstringprep工具与punycode已添加编码。
日期/时间类型¶
添加适合表示时间戳的日期和时间类型作为 datetime 模块。这些类型不支持不同的日历或许多花哨的功能,只需坚持表示时间的基本原则。
三种主要类型是: date 表示日、月、年; time ,包括小时、分钟和秒;以及 datetime ,其中包含 date 和 time . 还有一个 timedelta 类表示两个时间点之间的差异,时区逻辑由从抽象类继承的类实现。 tzinfo 类。
您可以创建 date 和 time 通过向适当的构造函数提供关键字参数,例如 datetime.date(year=1972, month=10, day=15) 或者使用许多类方法中的一种。例如, date.today() 类方法返回当前本地日期。
创建后,日期/时间类的实例都是不可变的。有许多方法可以从对象生成格式化字符串:
>>> import datetime
>>> now = datetime.datetime.now()
>>> now.isoformat()
'2002-12-30T21:27:03.994956'
>>> now.ctime() # Only available on date, datetime
'Mon Dec 30 21:27:03 2002'
>>> now.strftime('%Y %d %b')
'2002 30 Dec'
这个 replace() 方法允许修改 date 或 datetime 实例,返回新实例::
>>> d = datetime.datetime.now()
>>> d
datetime.datetime(2002, 12, 30, 22, 15, 38, 827738)
>>> d.replace(year=2001, hour = 12)
datetime.datetime(2001, 12, 30, 12, 15, 38, 827738)
>>>
实例可以进行比较、散列和转换为字符串(结果与 isoformat() ) date 和 datetime 实例可以彼此相减并添加到 timedelta 实例。最大的缺失特性是没有标准库支持解析字符串和返回 date 或 datetime .
有关更多信息,请参阅模块的参考文档。(蒂姆·彼得斯供稿)
optparse模块¶
这个 getopt 模块提供对命令行参数的简单分析。新的 optparse 模块(最初命名为optik)提供了更详细的命令行解析,遵循UNIX约定,自动为 --help ,可以对不同的选项执行不同的操作。
首先创建的实例 OptionParser 告诉它你的程序选项是什么。::
import sys
from optparse import OptionParser
op = OptionParser()
op.add_option('-i', '--input',
action='store', type='string', dest='input',
help='set input filename')
op.add_option('-l', '--length',
action='store', type='int', dest='length',
help='set maximum length of output')
然后通过调用 parse_args() 方法。::
options, args = op.parse_args(sys.argv[1:])
print options
print args
这将返回一个包含所有选项值的对象,以及一个包含其余参数的字符串列表。
使用各种参数调用脚本现在可以像您期望的那样工作。请注意,length参数将自动转换为整数。
$ ./python opt.py -i data arg1
<Values at 0x400cad4c: {'input': 'data', 'length': None}>
['arg1']
$ ./python opt.py --input=data --length=4
<Values at 0x400cad2c: {'input': 'data', 'length': 4}>
[]
$
将自动为您生成帮助消息:
$ ./python opt.py --help
usage: opt.py [options]
options:
-h, --help show this help message and exit
-iINPUT, --input=INPUT
set input filename
-lLENGTH, --length=LENGTH
set maximum length of output
$
有关更多详细信息,请参阅模块的文档。
optik由greg ward撰写,并有getopt sig读者的建议。
pymalloc:一个专门的对象分配器¶
pymalloc是VladimirMarangozov编写的一个专门的对象分配器,它是python 2.1中添加的一个特性。Pymalloc旨在比系统更快 malloc() 对于典型的python程序的分配模式,内存开销更少。分配器使用C malloc() 函数获取大型内存池,然后满足来自这些池的较小内存请求。
在2.1和2.2中,pymalloc是一个实验特性,默认情况下不启用;在编译python时,必须通过提供 --with-pymalloc 选择权 configure 脚本。在2.3中,pymalloc有了进一步的增强,现在默认情况下启用了;您必须提供 --without-pymalloc 禁用它。
这种更改对于用python编写的代码是透明的;但是,pymalloc可能会在C扩展中暴露bug。C扩展模块的作者应该在启用pymalloc的情况下测试其代码,因为某些不正确的代码可能会在运行时导致核心转储。
有一个特别常见的错误会引起问题。在python的c api中有许多内存分配函数以前只是c库的别名 malloc() 和 free() 也就是说,如果您不小心调用了不匹配的函数,则不会注意到错误。当启用对象分配器时,这些函数不是 malloc() 和 free() 如果再调用错误的函数来释放内存,可能会得到一个核心转储。例如,如果使用 PyObject_Malloc() ,必须使用 PyObject_Free() 不是 free() . 包含在Python中的一些模块遇到了这个问题,必须进行修复;毫无疑问,会有更多的第三方模块出现同样的问题。
作为这一变化的一部分,用于分配内存的令人困惑的多个接口被合并为两个API系列。分配给一个族的内存不能用另一个族的函数来操作。有一个系列用于分配内存块,另一个系列专门用于分配Python对象。
要分配和释放未区分的内存块,请使用“原始内存”系列:
PyMem_Malloc(),PyMem_Realloc()和PyMem_Free().“对象内存”系列是上述pymalloc设施的接口,倾向于大量“小”分配:
PyObject_Malloc(),PyObject_Realloc()和PyObject_Free().要分配和释放python对象,请使用“object”系列
PyObject_New(),PyObject_NewVar()和PyObject_Del().
由于TimPeters的大量工作,2.3中的pymalloc还提供了调试功能,可以捕获扩展模块和解释器本身的内存覆盖和双倍释放。要启用此支持,请通过运行 configure 具有 --with-pydebug .
为了帮助扩展写入程序,头文件 Misc/pymemcompat.h 与源代码一起分发到python 2.3,它允许python扩展在编译1.5.2以后的任何版本的python时使用2.3接口来分配内存。您将从python的源发行版复制该文件,并将其与扩展名的源捆绑在一起。
参见
- https://hg.python.org/cpython/file/default/Objects/obmalloc.c
有关pymalloc实现的完整详细信息,请参见文件顶部的注释。
Objects/obmalloc.c在python源代码中。上面的链接指向python.org svn浏览器中的文件。
构建和C API更改¶
对python构建过程和C API的更改包括:
垃圾收集使用的周期检测实现已经被证明是稳定的,所以现在它已经成为强制的。如果没有它,就不能再编译python,而且
--with-cycle-gc切换到 configure 已删除。现在可以选择将python构建为共享库 (
libpython2.3.so)通过供应--enable-shared当运行python的 configure 脚本。(由Ondrej Palkovsky提供。)这个
DL_EXPORT和DL_IMPORT宏现在已弃用。现在应该使用新宏声明python扩展模块的初始化函数PyMODINIT_FUNC,而python核心通常使用PyAPI_FUNC和PyAPI_DATA宏。通过提供
--without-doc-strings到 configure 脚本。这使得python可执行文件大约小了10%,但也意味着您无法获得关于python内置模块的帮助。(古斯塔沃·尼迈耶供稿)这个
PyArg_NoArgs()宏现在已弃用,应更改使用它的代码。对于python 2.2及更高版本,方法定义表可以指定METH_NOARGS标志,表示没有参数,然后可以删除参数检查。如果与2.2之前版本的python的兼容性很重要,那么代码可以使用PyArg_ParseTuple(args, "")相反,但这将比使用METH_NOARGS.PyArg_ParseTuple()接受不同大小的无符号整数的新格式字符:B对于 unsigned char ,H对于 unsigned short int ,I对于 unsigned int 和K对于 unsigned long long .新功能,
PyObject_DelItemString(mapping, char *key)被添加为PyObject_DelItem(mapping, PyString_New(key)).文件对象现在以不同的方式管理其内部字符串缓冲区,在需要时以指数形式增加缓冲区。这导致在
Lib/test/test_bufio.py大幅加速(根据一项测量,从57秒到1.7秒)。现在可以通过设置
METH_CLASS或METH_STATIC方法中的标志PyMethodDef结构。python现在包含expat-xml解析器源代码的副本,消除了对系统版本或expat本地安装的任何依赖。
如果在扩展中动态地分配类型对象,则应该注意与
__module__和__name__属性。总之,您需要确保类型的字典包含'__module__'键;使模块名称成为类型名称中最后一个句点之前的部分将不再具有所需的效果。有关更多详细信息,请阅读API参考文档或源代码。
端口特定更改¶
对使用EMX运行时环境的IBM OS/2端口的支持被合并到主python源代码树中。EMX是OS/2系统API上的POSIX仿真层。EMX的python端口试图支持EMX运行时公开的所有类似posix的功能,但大多数都成功了; fork() 和 fcntl() 受到底层仿真层的限制。标准OS/2端口使用IBM的VisualAge编译器,作为EMX端口与CVS集成的一部分,它还获得了对大小写敏感的导入语义的支持。(安德鲁·麦金泰尔供稿)
在MacOS上,大多数工具箱模块的链接都很弱,以提高向后兼容性。这意味着,如果当前操作系统版本上缺少单个例程,模块将不再无法加载。相反,调用缺少的例程将引发异常。(杰克·詹森供稿)
RPM规范文件,在 Misc/RPM/ python源发行版中的目录已针对2.3进行了更新。(肖恩·雷夫施耐德供稿)
现在Python支持的其他新平台包括Atheos(http://www.atheos.cx/)、GNU/hurd和OpenVMS。
其他更改和修复¶
像往常一样,在源代码树中散布着许多其他的改进和错误修复。通过对cvs变更日志的搜索,发现应用了523个补丁,并修复了python 2.2和2.3之间的514个bug。这两个数字都可能被低估。
一些更显著的变化是:
如果
PYTHONINSPECT设置环境变量后,python解释器将在运行python程序后进入交互式提示,就好像用-i选择权。环境变量可以在运行python解释器之前设置,也可以由python程序在执行过程中设置。这个
regrtest.py脚本现在提供了一种允许“除 foo “传递给-u选项现在可以用连字符作为前缀 ('-')例如,选项“-uall,-bsddb```可用于启用除 ``bsddb` .用于构建文档的工具现在可以在Cygwin和Unix下工作。
这个
SET_LINENO操作码已被删除。回到时间的迷雾中,这个操作码需要在回溯中产生行号并支持追踪函数(例如,pdb)自python 1.5以来,回溯中的行号是使用另一种机制计算出来的,该机制与“python-o”一起工作。对于Python2.3,MichaelHudson实现了一个类似的方案来确定何时调用跟踪函数,从而消除了SET_LINENO完全。除了在运行python时稍微加快速度之外,很难检测到python代码产生的任何差异。
-O.C扩展访问
f_lineno帧对象字段应改为调用PyCode_Addr2Line(f->f_code, f->f_lasti). 在早期版本的python中,这将使代码在“python-o”下工作,从而产生额外的效果。一个漂亮的新特性是跟踪函数现在可以分配给
f_lineno帧对象的属性,更改将在下一步执行的行。Ajump命令已添加到pdb调试器利用了这个新特性。(由Richie Hindle实施。)
移植到python 2.3¶
本节列出了前面描述的可能需要更改代码的更改:
yield现在始终是关键字;如果它在代码中用作变量名,则必须选择其他名称。弦乐 X 和 Y ,
X in Y现在工作如果 X 长度超过一个字符。这个
int()类型构造函数现在将返回一个长整数,而不是引发OverflowError当字符串或浮点数太大而无法放入整数时。如果您有包含8位字符的Unicode字符串,则必须通过在文件顶部添加注释来声明文件的编码(UTF-8、Latin-1或其他)。见节 PEP 263:源代码编码 更多信息。
通过调用tcl方法
_tkinter不再只返回字符串。相反,如果tcl返回其他对象,则这些对象将转换为它们的python等效对象(如果存在),或者用_tkinter.Tcl_Obj对象,如果不存在等效的python。大型八进制和十六进制文本,如
0xffffffff现在触发FutureWarning. 目前,它们被存储为32位数字并产生负值,但在Python2.4中,它们将成为正长整数。有几种方法可以修复此警告。如果您真的需要一个正数,只需添加一个
L到文字的结尾。如果您试图获得一个32位整数,并且设置了低位,并且以前使用过一个表达式,例如~(1 << 31),可能最清楚的方法是从所有的位开始设置并清除所需的高位。例如,要只清除最高位(位31),可以写入0xffffffffL &~(1L<<31).您不能再通过分配给
__debug__.ditudil
setup()函数获得了各种新的关键字参数,例如 取决于 . 如果传递未知关键字,则distutils的旧版本将中止。解决方案是检查是否存在新的get_distutil_options()在您的setup.py并且只将新关键字与支持它们的distuils版本一起使用:from distutils import core kw = {'sources': 'foo.c', ...} if hasattr(core, 'get_distutil_options'): kw['depends'] = ['foo.h'] ext = Extension(**kw)
使用
None作为变量名,现在将导致SyntaxWarning警告。由包含在python中的模块定义的扩展类型的名称现在包含模块和
'.'在类型名称前面。
确认¶
作者要感谢以下人员对本文的各种草稿提供建议、更正和帮助:Jeff Bauer、Simon Brunning、Brett Cannon、Michael Chermside、Andrew Dalke、Scott David Daniels、Fred L.Drake,Jr.、David Fraser、Kelly Gerber、Raymond Hettinger、Michael Hudson、Chris Lambert、Detlef LanneRT、Martin von L_wis、Andrew Macintyre、Lalo Martins、Chad Netzer、Gustavo Niemeyer、Neal Norwitz、Hans Nowak、Chris Reedy、Francesco Ricciardi、Vinay Sajip、Neil Schemenauer、Roman Suzi、Jason Tishler、Just van Rossum。