Python 2.3 新增Function

  • Author

    • A.M. Kuchling

本文介绍了 Python 2.3 中的新Function。 Python 2.3 于 2003 年 7 月 29 日发布。

Python 2.3 的主要主题是完善 2.2 中添加的一些Function,对核心语言进行各种小的但有用的增强,以及扩展标准库。先前版本中引入的新对象模型受益于 18 个月的错误修正以及优化工作,这些工作改善了new-style类的性能。添加了一些新的内置函数,例如sum()enumerate()in运算符现在可以用于子字符串搜索(例如"ab" in "abc"返回True)。

许多新的库Function包括布尔,集,堆和日期/时间数据类型,从 ZIP 格式 Files 导入模块的Function,对期待已久的 Python 目录的元数据支持,IDLE 的更新版本以及模块使用 BerkeleyDB 数据库记录消息,包装文本,解析 CSV 文件,处理命令行选项,使用新的和增强的模块,这些列表很长。

本文并不试图提供新Function的完整规范,而是提供了一个方便的概述。有关完整的详细信息,您应该参考 Python 2.3 的文档,例如《 Python 库参考》和《 Python 参考手册》。如果您想了解完整的实现和设计原理,请参考 PEP 以获得特定的新Function。

PEP 218:标准集数据类型

新的sets模块包含一个 set 数据类型的实现。 Set类用于可变集,可以添加和删除成员的集。 ImmutableSet类用于无法修改的集合,因此ImmutableSet的实例可以用作字典键。集是构建在词典之上的,因此集内的元素必须是可哈希的。

这是一个简单的例子:

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

See also

  • PEP 218-添加内置 Set 对象类型

  • PEP 由 Greg V. Wilson 写。由 Greg V. Wilson,Alex Martelli 和 GvR 实施。

PEP 255:简单生成器

在 Python 2.2 中,生成器被添加为可选Function,可passfrom __future__ import generators指令启用。在 2.3 版中,不再需要专门启用生成器,并且现在始终可以使用它们;这意味着yield现在始终是关键字。本节的其余部分是“ Python 2.2 的新增Function”文档中有关生成器的描述的副本。如果您在 Python 2.2 发布时将其读回,则可以跳过本节的其余部分。

您毫无疑问地熟悉函数调用在 Python 或 C 中的工作方式。当您调用函数时,它会获得一个私有的命名空间,用于创建其局部变量。当函数到达return语句时,局部变量将被销毁并将结果值返回给调用方。以后调用同一函数将获得一组新的局部变量。但是,如果在退出函数时没有扔掉局部变量怎么办?如果您以后可以在break的地方 continue 运行该怎么办?这就是 Generator 提供的;可以将它们视为可恢复的Function。

这是生成器函数的最简单示例:

def generate_ints(N):
    for i in range(N):
        yield i

为生成器引入了一个新关键字yield。任何包含yield语句的函数都是生成器函数;这是由 Python 的字节码编译器检测到的,该编译器因此专门编译了该函数。

调用生成器函数时,它不会返回单个值;而是返回一个支持迭代器协议的生成器对象。执行yield语句后,生成器将输出i的值,类似于return语句。 yieldreturn语句之间的最大区别在于,到达yield时,生成器的执行状态被挂起,并且保留了局部变量。在下一次调用生成器的.next()方法时,该函数将在yield语句之后立即恢复执行。 (由于复杂的原因,在tryfinally语句的try块中不允许使用yield语句;请阅读 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 5return是生成器函数内部的语法错误。生成器结果的结尾也可以pass手动提高StopIteration或仅让执行流程脱离函数的底部来指示。

pass编写自己的类并将生成器的所有局部变量存储为实例变量,可以手动实现生成器的效果。例如,返回整数列表可以pass将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 皇后问题提供了解决方案(将$ N $皇后放置在$ NxN $棋盘上,这样就没有女王可以威胁另一个皇后)和 Knight's Tour(骑士之旅),该 Route 需要骑士到$$的每个平方 NxN $棋盘,而无需两次访问任何正方形)。

生成器的思想来自其他编程语言,尤其是 Icon(https://www.cs.arizona.edu/icon/),其中生成器的思想很重要。在 Icon 中,每个表达式和函数调用的行为都类似于生成器。 https://www.cs.arizona.edu/icon/docs/ipd266.htm的“图标编程语言概述”中的一个示例给出了一个大概的概念:

sentence := "Store it in the neighboring harbor"
if (i := find("or", sentence)) > 5 then write(i)

在 Icon 中,find()函数返回在其中找到子字符串“ or”的索引:3,23,33.在if语句中,i首先被赋值为 3,但 3 小于 5,因此比较失败, Icon 用第二个值 23 重试它。23 大于 5,所以现在比较成功,并且代码将值 23 打印到屏幕上。

在采用生成器作为中心概念的过程中,Python 远不及 Icon。生成器被认为是 Python 核心语言的一部分,但是学习或使用它们不是强制性的。如果他们不能解决您遇到的任何问题,请随时忽略它们。与 Icon 相比,Python 界面的一个新颖 Feature 是生成器的状态表示为具体对象(迭代器),可以将其传递给其他函数或存储在数据结构中。

See also

  • PEP 255-简单生成器

  • 由 Neil Schemenauer,Tim Peters 和 Magnus Lie Hetland 撰写。主要由 Neil Schemenauer 和 Tim Peters 实施,以及 Python Labs 小组的其他修复程序。

PEP 263:源代码编码

现在可以将 Python 源文件语句为不同的字符集编码。pass在源文件的第一行或第二行中包含特殊格式的 Comments 来语句编码。例如,可以使用以下内容语句 UTF-8 文件:

#!/usr/bin/env python
# -*- coding: UTF-8 -*-

如果没有这样的编码语句,则使用的默认编码是 7 位 ASCII。执行或导入包含具有 8 位字符的字符串 Literals 且没有编码语句的模块,将导致 Python 2.3 发出DeprecationWarningsignal;在 2.4 中,这将是语法错误。

编码语句仅影响 Unicode 字符串 Literals,这些 Literals 将使用指定的编码转换为 Unicode。请注意,Python 标识符仍然限于 ASCII 字符,因此您不能拥有使用普通字母数字之外的字符的变量名。

See also

  • PEP 263-定义 Python 源代码编码

  • 由 Marc-AndréLemburg 和 Martin vonLöwis 撰写;由 Suzuki Hisao 和 Martin vonLö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 将不会trypass添加相应的*.pyc文件来修改存档,这意味着,如果 ZIP 存档中不包含*.pyc文件,则导入可能会很慢。

也可以将 Files 中的路径指定为仅从子目录导入;例如,路径/tmp/example.zip/lib/将仅从存档中的lib/子目录导入。

See also

  • PEP 273-从 Zip 存档导入模块

  • 由 James C. Ahlstrom 撰写,他也提供了一个实现。 Python 2.3 遵循 PEP 273中的规范,但是使用 Just van Rossum 编写的实现,该实现使用 PEP 302中描述的导入钩子。有关新导入钩子的说明,请参见PEP 302:新的 import 钩子部分。

PEP 277:Windows NT 支持 Unicode 文件名

在 Windows NT,2000 和 XP 上,系统将文件名存储为 Unicode 字符串。传统上,Python 将文件名表示为字节字符串,这是不够的,因为它使某些文件名不可访问。

Python 现在允许对所有需要文件名的函数使用任意 Unicode 字符串(在文件系统的限制内),最著名的是open()内置函数。如果将 Unicode 字符串传递给os.listdir(),Python 现在将返回 Unicode 字符串列表。新函数os.getcwdu()返回当前目录作为 Unicode 字符串。

字节字符串仍然可以作为文件名,在 Windows 上,Python 会使用mbcs编码将其透明地转换为 Unicode。

其他系统还允许将 Unicode 字符串用作文件名,但在将它们传递给系统之前将它们转换为字节字符串,这可能导致引发UnicodeError。应用程序可以pass检查os.path.supports_unicode_filenames(一个布尔值)来测试是否支持将任意 Unicode 字符串作为文件名。

在 MacOS 下,os.listdir()现在可以返回 Unicode 文件名。

See also

  • PEP 277-Windows NT 的 Unicode 文件名支持

  • 尼尔·霍奇森(Neil Hodgson)撰写;由 Neil Hodgson,Martin vonLöwis 和 Mark Hammond 实施。

PEP 278:通用换行符支持

今天使用的三种主要 os 是 Microsoft Windows,Apple 的 Macintosh OS 和各种 Unix 派生产品。跨平台工作的一个小问题是这三个平台都使用不同的字符来标记文本文件中的行尾。 Unix 使用换行符(ASCII 字符 10),MacOS 使用回车符(ASCII 字符 13),Windows 使用由回车符和换行符组成的两个字符的序列。

Python 的文件对象现在可以支持行尾约定,而不是行末约定,后跟约定是运行 Python 的平台。以'U''rU'模式打开文件将打开文件以universal newlines模式读取。这三种行尾约定将在各种文件方法(例如read()readline())返回的字符串中转换为'\n'

导入模块和使用execfile()函数执行文件时,也使用通用换行符支持。这意味着 Python 模块可以在所有三个 os 之间共享,而无需转换行尾。

pass在运行 Python 的 configure 脚本时指定--without-universal-newlines开关,可以在编译 Python 时禁用此Function。

See also

  • PEP 278-通用换行符支持

  • 由杰克·詹森(Jack Jansen)编写和实施。

PEP 279:enumerate()

新的内置函数enumerate()将使某些循环更清晰。 enumerate(thing),其中* 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()重写为:

for i, item in enumerate(L):
    # ... compute some result based on item ...
    L[i] = result

See also

  • PEP 279-enumerate()内置函数

  • 由 Raymond D. Hettinger 撰写和实施。

PEP 282:日志记录程序包

Python 2.3 已添加了一个用于写入日志的标准软件包logging。它提供了一种强大而灵活的机制来生成日志记录输出,然后可以以各种方式对其进行过滤和处理。以标准格式编写的配置文件可用于控制程序的日志记录行为。 Python 包含处理程序,这些处理程序会将日志记录写入标准错误或文件或套接字,将它们发送到系统日志,甚至pass电子邮件发送到特定地址。当然,也可以编写自己的处理程序类。

Logger类是主要类。大多数应用程序代码将处理一个或多个Logger对象,每个对象由应用程序的特定子系统使用。每个Logger都由一个名称标识,并且使用.作为组件分隔符将名称组织到一个层次结构中。例如,您可能有Logger个实例,分别名为serverserver.authserver.network。后两个实例在层次结构中的server下面。这意味着,如果您提高server的详细程度或将server消息定向到其他处理程序,则更改还将应用于记录到server.authserver.network的记录。还有一个根Logger,它是所有其他 Logger 的父级。

为简单起见,logging软件包包含一些始终使用根日志的便捷Function:

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

在默认配置中,信息和调试消息被抑制,并且输出被发送到标准错误。您可以pass在根 Logger 上调用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

稍微高级的程序将使用除根 Logger 以外的其他 Logger。 getLogger(name)函数用于获取特定日志,如果尚不存在,则创建该日志。 getLogger(None)返回根 Logger。

log = logging.getLogger('server')
 ...
log.info('Listening on port %i', port)
 ...
log.critical('Disk full')
 ...

日志记录通常在层次结构中传播,因此serverroot也会看到记录到server.auth的消息,但是Logger可以pass将其propagate属性设置为False来防止这种情况。

logging软件包提供了更多可以自定义的类。当Logger实例被告知记录消息时,它将创建一个LogRecord实例,该实例被发送到任意数量的不同Handler实例。Logger 和处理程序还可以具有附加的过滤器列表,每个过滤器都可以导致LogRecord被忽略,或者可以在传递记录之前对其进行修改。finally输出它们后,Formatter类将LogRecord实例转换为文本。所有这些类都可以用自己编写的类替换。

具有所有这些Function,logging软件包甚至应为最复杂的应用程序提供足够的灵 Active。这只是其Function的不完整概述,因此,请参阅软件包的参考文档以获取所有详细信息。阅读 PEP 282也将有所帮助。

See also

  • PEP 282-记录系统

  • 由 Vinay Sajip 和 Trent Mick 撰写;由 Vinay Sajip 实施。

PEP 285:布尔类型

布尔类型已添加到 Python 2.3. 向builtin模块TrueFalse添加了两个新常量。 (TrueFalse常量已添加到 Python 2.2.1 的内置函数中,但 2.2.1 版本仅设置为 1 和 0 的整数值,并且没有不同的类型。)

此新类型的类型对象名为bool;它的构造函数采用任何 Python 值并将其转换为TrueFalse

>>> 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 的布尔值。诸如 Pascal 之类的非常严格的语言也会阻止您使用布尔值执行算术运算,并且会要求if语句中的表达式始终求值为布尔值。正如 PEP 285明确指出的那样,Python 并不严格,也永远不会严格。这意味着您仍然可以在if语句中使用任何表达式,即使是评估为列表或 Tuples 或某个随机对象的表达式。布尔类型是int类的子类,因此使用布尔的算术仍然有效。

>>> True + 1
2
>>> False + 1
1
>>> False * 75
0
>>> True * 75
75

总结一句话中的TrueFalse:它们是拼写整数值 1 和 0 的替代方法,唯一的区别是str()repr()返回字符串'True''False'而不是'1''0'

See also

  • PEP 285-添加布尔类型

  • 由 GvR 编写并实施。

PEP 293:编解码器错误处理回调

将 Unicode 字符串编码为字节字符串时,可能会遇到无法编码的字符。到目前为止,Python 允许将错误处理指定为“ strict”(提高UnicodeError),“ ignore”(跳过字符)或“ replace”(在输出字符串中使用问号),其中“ strict”为默认行为。可能需要指定此类错误的替代处理,例如将 XML 字符引用或 HTML 实体引用插入转换后的字符串中。

Python 现在具有灵活的框架来添加不同的处理策略。可以使用codecs.register_error()添加新的错误处理程序,然后编解码器可以使用codecs.lookup_error()访问错误处理程序。已为用 C 编写的编解码器添加了等效的 C API。错误处理程序获取必要的状态信息,例如正在转换的字符串,字符串在其中检测到错误的位置以及目标编码。然后,处理程序可以引发异常或返回替换字符串。

使用此框架还实现了两个其他的错误处理程序:“ backslashreplace”使用 Python 反斜杠引号表示无法编码的字符,而“ xmlcharrefreplace”发出 XML 字符引用。

See also

  • PEP 293-编解码器错误处理回调

  • 由 WalterDörwald 编写和实施。

PEP 301:Distutils 的软件包索引和元数据

对请求已久的 Python 目录的支持在 2.3 中首次出现。

目录的核心是新的 Distutils register 命令。运行python setup.py register将收集描述程序包的元数据(例如其名称,版本,维护者,描述等),并将其发送到中央目录服务器。生成的目录可从https://pypi.org获得。

为了使目录更加有用,已向 Distutils setup()函数添加了新的可选* classifiers *关键字参数。可以提供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)

分类器的完整列表可以pass运行python setup.py register --list-classifiers获得。

See also

  • PEP 301-Distutils 的软件包索引和元数据

  • 由 Richard Jones 编写和实施。

PEP 302:新导入钩子

自从 Python 1.3 引入ihooks模块以来,就可以编写自定义导入钩子了,但是没人对它感到 true 满意,因为编写新的导入钩子既困难又麻烦。已经提出了各种各样的替代方案,例如imputiliu模块,但是它们中没有一个获得了广泛的接受,并且它们都不容易从 C 代码中使用。

PEP 302借鉴了其前任的想法,尤其是戈登·麦克米兰(Gordon McMillan)的iu模块。 sys模块中添加了三个新项目:

  • sys.path_hooks是可调用对象的列表;大多数情况下,它们将是类。每个可调用对象都包含一个包含路径的字符串,并返回一个导入器对象,该对象将处理从此路径的导入,或者如果无法处理此路径,则会引发ImportError异常。

  • sys.path_importer_cache为每个路径缓存导入器对象,因此对于每个路径,只需遍历sys.path_hooks一次。

  • sys.meta_path是在检查sys.path之前将遍历的导入器对象列表。该列表最初是空的,但是用户代码可以向其中添加对象。可以pass添加到此列表的对象来导入其他内置模块和冻结模块。

导入器对象必须具有一个单一方法find_module(fullname, path=None)全名将是模块或软件包的名称,例如stringdistutils.corefind_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

See also

  • PEP 302-新的导入钩子

  • 由 Just van Rossum 和 Paul Moore 撰写。由 Just van Rossum 实施。

PEP 305:逗号分隔的文件

逗号分隔文件是一种常用于从数据库和电子表格中导出数据的格式。 Python 2.3 为逗号分隔的文件添加了一个解析器。

乍看之下,逗号分隔格式看似简单:

Costs,150,200,3.95

读一行并致电line.split(','):有什么更简单的方法?但是,如果 Importing 可能包含逗号的字符串数据,事情就会变得更加复杂:

"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类将从一系列 Tuples 或列表中生成逗号分隔的文件,并引用包含定界符的字符串。

See also

  • PEP 305-CSV 文件 API

  • 由 Kevin Altis,Dave Cole,Andrew McNamara,Skip Montanaro,Cliff Wells 编写和实施。

PEP 307:pickle 增强Function

在 2.3 开发周期中,picklecPickle模块受到关注。在 2.2 中,可以很容易地对新样式的类进行腌制,但是它们并不是很紧凑地腌制。 PEP 307引用了一个简单的示例,其中,新类产生的腌制字符串比经典类产生的字符串长三倍。

解决的办法是发明一个新的 pickle 协议。 pickle.dumps()函数很长时间以来一直支持文本或二进制标志。在 2.3 中,此标志从布尔值重新定义为整数:0 是旧的文本模式 pickle 格式,1 是旧的二进制格式,现在 2 是新的 2.3 特定格式。一个新的常数pickle.HIGHEST_PROTOCOL可以用来选择最合适的协议。

脱酸不再被认为是安全的操作。 2.2 的pickle提供了钩子,用于try防止不安全的类被解开(特别是__safe_for_unpickling__属性),但是这些代码都没有经过审核,因此在 2.3 中已将其全部删除。您不应在任何版本的 Python 中释放不受信任的数据。

为了减少新样式类的 Pickling 开销,使用三种特殊方法添加了用于自定义 Pickling 的新接口:getstate()setstate()getnewargs()。有关这些方法的完整语义,请参见 PEP 307

作为进一步压缩 pickle 的一种方法,现在可以使用整数代码代替长字符串来识别 pickle 类。 Python 软件基金会将维护一份标准化代码列表;还有一系列供私人使用的代码。当前没有指定代码。

See also

  • PEP 307-pickle 协议的扩展

  • 由 Guido van Rossum 和 Tim Peters 编写和实施。

Extended Slices

从 Python 1.4 开始,切片语法一直支持可选的第三个“ step”或“ stride”参数。例如,这些都是合法的 Python 语法:L[1:10:2]L[:-1:1]L[::-1]。应数值 Python 开发人员的要求,将其添加到 Python 中,后者广泛使用了第三个参数。但是,Python 的内置列表,Tuples 和字符串序列类型从不支持此Function,如果try过,则会引发TypeError。迈克尔·哈德森(Michael Hudson)提供了一个补丁来解决此缺陷。

例如,您现在可以轻松提取具有偶数索引的列表元素:

>>> L = range(10)
>>> L[::2]
[0, 2, 4, 6, 8]

负值也可以以相反的 Sequences 复制相同列表:

>>> L[::-1]
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

这也适用于 Tuples,数组和字符串:

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

或直接在下标中使用切片对象:

>>> range(10)[slice(0, 5, 2)]
[0, 2, 4]

为了简化实现支持扩展切片的序列,现在切片对象具有方法indices(length),给定序列的长度,该方法返回(start, stop, step)Tuples,该 Tuples 可以直接传递给range()indices()以与常规切片一致的方式处理Ellipsis的索引和越界索引(并且这个无害的短语隐藏了令人困惑的细节!)。该方法旨在像这样使用:

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 一致,其中intstr等进行了相同的更改。

其他语言更改

以下是 Python 2.3 对核心 Python 语言所做的所有更改。

  • yield语句现在始终是关键字,如本文档的PEP 255:简单生成器部分所述。

  • 如本文档第PEP 279:enumerate()节中所述,添加了新的内置函数enumerate()

  • 如本文档的PEP 285:布尔类型部分所述,添加了两个新的常量TrueFalse以及内置的bool类型。

  • 现在,当字符串或浮点数太大而无法容纳整数时,int()类型的构造函数将返回一个长整数而不是引发OverflowError。这可能导致isinstance(int(expression), int)为 Pseudo 反常结果,但这似乎不太可能在实践中引起问题。

  • 内置类型现在支持扩展的切片语法,如本文档第Extended Slices节中所述。

  • 新的内置函数sum(iterable, start=0),将可迭代对象中的数字项相加并返回它们的总和。 sum()仅接受数字,这意味着您不能使用它来连接一串字符串。 (由 Alex Martelli 提供.)

  • list.insert(pos, value)过去在* pos 为负数时将 value 插入列表的开头。现在已更改了行为,使其与切片索引保持一致,因此当 pos *为-1 时,该值将插入到最后一个元素之前,依此类推。

  • list.index(value)在列表中搜索* value 并返回其索引,现在使用可选的 start stop *参数将搜索限制在列表的一部分。

  • 字典有一个新方法pop(key[, *default*]),该方法返回对应于* key 的值,并从字典中删除该键/值对。如果字典中不存在请求的键,则如果指定了 default ,则返回 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),它使用从提供的迭代器* iterable 获取的键创建一个字典,并且所有值都设置为 value *,默认为None

(由 Raymond Hettinger 提供的补丁.)

而且,dict()构造函数现在接受关键字参数以简化创建小词典的过程:

>>> dict(red=1, blue=2, green=3, black=4)
{'blue': 2, 'black': 4, 'green': 3, 'red': 1}

(由 Just van Rossum 提供.)

  • assert语句不再检查__debug__标志,因此您不能再pass分配给__debug__来禁用 assert。使用-O开关运行 Python 仍会生成不执行任何 assert 的代码。

  • 现在大多数类型对象都是可调用的,因此您可以使用它们来创建新对象,例如函数,类和模块。 (这意味着new模块可以在将来的 Python 版本中弃用,因为您现在可以使用types模块中可用的类型对象。)例如,您可以使用以下代码创建一个新的模块对象:

>>> import types
>>> m = types.ModuleType('abc','docstring')
>>> m
<module 'abc' (built-in)>
>>> m.__doc__
'docstring'
  • 添加了一个新的警告PendingDeprecationWarning,以指示不赞成使用的Function。默认情况下,不会打印警告。要检查将来将不推荐使用的Function的使用,请在命令行上提供-Walways::PendingDeprecationWarning::或使用warnings.filterwarnings()

  • 否决基于raise "Error occurred"的基于字符串的异常的过程已经开始。引发字符串现在将触发PendingDeprecationWarning

  • 现在使用None作为变量名将产生SyntaxWarning警告。在 Python 的 Future 版本中,None可能finally成为关键字。

  • 不再需要在 Python 2.1 中引入文件对象的xreadlines()方法,因为文件现在可以充当其自己的迭代器。最初引入xreadlines()是一种循环遍历文件中所有行的更快方法,但是现在您只需编写for line in file_obj即可。文件对象还具有一个新的只读encoding属性,该属性提供文件使用的编码。写入文件的 Unicode 字符串将使用给定的编码自动转换为字节。

  • new-style类使用的方法解析 Sequences 已更改,但是只有在您拥有非常复杂的继承层次结构时,您才会注意到其中的区别。经典类不受此更改的影响。 Python 2.2 最初使用的是类祖先的拓扑结构,但现在使用的是 C3 算法,如论文“迪伦的单调超类线性化”中所述。要了解进行此更改的动机,请阅读 Michele Simionato 的文章“ Python 2.3 方法解析 Sequences”,或者阅读 python-dev 上的线程,其起始消息为https://mail.python.org/pipermail/python-dev/2002-October/029035.html。 Samuele Pedroni 首先指出了问题,并且还pass对 C3 算法进行编码来实现了此修复程序。

  • Python pass在执行 N 个字节码后在线程之间切换来运行多线程程序。 N 的默认值已从 10 个字节码增加到 100 个字节码,pass减少切换开销来加快单线程应用程序。某些多线程应用程序的响应时间可能会变慢,但是可以pass使用sys.setcheckinterval(N)将限制设置回较小的值来轻松解决。可以使用新的sys.getcheckinterval()函数检索该限制。

  • 一个较小但影响深远的更改是,Python 随附的模块定义的扩展类型的名称现在包含该模块,并且在类型名称之前包含一个'.'。例如,在 Python 2.2 中,如果创建了一个套接字并打印了它的__class__,则会得到以下输出:

>>> s = socket.socket()
>>> s.__class__
<type 'socket'>

在 2.3 中,您得到以下信息:

>>> s.__class__
<type '_socket.socket'>
  • 消除了旧类和新类之间的一种不兼容现象:现在,您可以分配新类的namebases属性。对于可以分配给bases的内容有一些限制,具体取决于与分配给实例的class属性有关的限制。

String Changes

  • in运算符现在对字符串的工作方式有所不同。以前,在评估X in Y时,* X Y 是字符串, X *只能是单个字符。现在已经改变了; * X 可以是任意长度的字符串,如果 X Y 的子字符串,则X in Y将返回True。如果 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 建议,由 WalterDörwald 实施.)

  • startswith()endswith()字符串方法现在接受* start end *参数的负数。

  • 另一个新的字符串方法是zfill(),最初是string模块中的函数。 zfill()将左边的零填充数字字符串,直到达到指定的宽度为止。请注意,%运算符比zfill()更加灵活和强大。

>>> '45'.zfill(4)
'0045'
>>> '12345'.zfill(4)
'12345'
>>> 'goofy'.zfill(6)
'0goofy'

(由 WalterDörwald 提供.)

  • 已添加新的对象basestring。 8 位字符串和 Unicode 字符串都从该类型继承,因此isinstance(obj, basestring)将针对任何一种字符串返回True。这是一个完全抽象的类型,因此您无法创建basestring实例。

  • 实习生字符串不再是不朽的,现在,当它们唯一的引用来自实习生字符串的内部字典时,将以通常的方式进行垃圾回收。 (由 Oren Tirosh 实施.)

Optimizations

  • 创建new-style类实例的速度大大加快了。他们现在比经典班快!

  • Lists 对象的sort()方法已由 Tim Peters 广泛重写,实现起来明显更快。

  • 现在,大长整数的乘法要快得多,这要归功于 Karatsuba 乘法的实现,Karatsuba 乘法的可扩展性比小学生乘法算法所需的 O(n * n)好。 (克里斯托弗·A·克雷格(Christopher A. Craig)的原始补丁,蒂姆·彼得斯(Tim Peters)对其进行了重大修改。

  • SET_LINENO操作码现已消失。根据编译器的特性,这可能会提高速度。有关详细说明,请参见第其他更改和修复节。 (由 Michael Hudson 删除.)

  • 现在xrange()个对象具有自己的迭代器,从而使for i in xrange(n)for i in range(n)快一点。 (Raymond Hettinger 的补丁.)

  • 在各种热点中进行了许多小的重新排列,以提高性能,例如内联函数或删除一些代码。 (主要由 GvR 实施,但是很多人做出了单个更改.)

2.3 优化的finally结果是,Python 2.3 运行 pystone 基准比 Python 2.2 快 25%。

新增,改进和不推荐使用的模块

像往常一样,Python 的标准库获得了许多增强Function和错误修复。这是最值得注意的更改的部分列表,按模块名称的字母 Sequences 排列。请查阅源代码树中的Misc/NEWS文件以获得更完整的更改列表,或查看 CVS 日志以获取所有详细信息。

  • array模块现在支持使用'u'格式字符的 Unicode 字符数组。数组现在还支持使用+=赋值运算符添加另一个数组的内容,并使用*=赋值运算符重复一个数组。 (由 Jason Orendorff 提供.)

  • bsddb模块已被PyBSDDB软件包的版本 4.1.6 取代,为 BerkeleyDB 库的事务Function提供了更完整的接口。

该模块的旧版本已重命名为bsddb185,并且不再自动构建。您必须编辑Modules/Setup才能启用它。请注意,新的bsddb软件包旨在与旧模块兼容,因此,如果发现任何不兼容性,请务必提交错误。升级到 Python 2.3 时,如果新解释器是使用基础 BerkeleyDB 库的新版本编译的,则几乎可以肯定,您必须将数据库文件转换为新版本。您可以使用新脚本db2pickle.pypickle2db.py轻松实现此目的,您可以在发行版的Tools/scripts目录中找到它们。如果您已经在使用 PyBSDDB 软件包并将其导入为bsddb3,则必须更改import语句以将其导入为bsddb

  • 新的bz2模块是 bz2 数据压缩库的接口。 bz2 压缩的数据通常小于相应的zlib压缩的数据。 (由 Gustavo Niemeyer 提供.)

  • 在新的datetime模块中添加了一组标准日期/时间类型。有关更多详细信息,请参见以下部分。

  • Distutils Extension类现在支持一个名为* depends *的附加构造函数参数,用于列出扩展所依赖的其他源文件。如果修改了任何依赖文件,这将使 Distutils 重新编译模块。例如,如果sampmodule.c包含头文件sample.h,则可以这样创建Extension对象:

ext = Extension("samp",
                sources=["sampmodule.c"],
                depends=["sample.h"])

修改sample.h会导致模块重新编译。 (由杰里米·海尔顿(Jeremy Hylton)提供。)

  • 对 Distutils 的其他较小更改:现在,它检查 CC CFLAGS CPP LDFLAGS CPPFLAGS环境变量,使用它们覆盖 Python 配置中的设置(由 Robert Weber 贡献)。

  • 以前,doctest模块仅在公共方法和函数的文档字符串中搜索测试用例,但现在它也在检查私有方法和函数。 DocTestSuite()函数从一组doctest测试创建一个unittest.TestSuite对象。

  • 新的gc.get_referents(object)函数返回* object *引用的所有对象的列表。

  • getopt模块获得了一个新函数gnu_getopt(),该函数支持与现有getopt()函数相同的参数,但是使用 GNU 样式的扫描模式。现有的getopt()会在遇到非选项参数时立即停止处理选项,但是在 GNU 样式模式下,处理会 continue 进行,这意味着选项和参数可以混合使用。例如:

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

(由 PeterÅstrand 提供.)

>>> import grp
>>> g = grp.getgrnam('amk')
>>> g.gr_name, g.gr_gid
('amk', 500)
  • gzip模块现在可以处理超过 2 GiB 的文件。

  • 新的heapq模块包含一个堆队列算法的实现。堆是一种类似于数组的数据结构,它以部分排序的 Sequences 保留项目,以便对于每个索引* k *,heap[k] <= heap[2*k+1]heap[k] <= heap[2*k+2]。这样可以快速删除最小的项目,并在保持堆属性为 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]

(由 Kevin O'Connor 贡献.)

  • 已使用 IDLEfork 项目(http://idlefork.sourceforge.net)中的代码更新了 IDLE 集成开发环境。最显着的Function是,正在开发的代码现在在子流程中执行,这意味着不再需要手动进行reload()操作。 IDLE 的核心代码已作为idlelib软件包并入标准库。

  • imaplib模块现在支持基于 SSL 的 IMAP。 (由 Piers Lauder 和 Tino Lange 贡献.)

  • itertools包含许多有用的与迭代器一起使用的Function,这些Function受 ML 和 Haskell 语言提供的各种Function的启发。例如,itertools.ifilter(predicate, iterator)返回迭代器中的所有元素,其中函数predicate()返回True,而itertools.repeat(obj, N)返回obj * N *次。模块中还有许多其他Function。有关详细信息,请参见软件包的参考文档。 (由 Raymond Hettinger 提供.)

  • math模块中的两个新函数degrees(rads)radians(degs)在弧度和度之间转换。 math模块中的其他Function(例如math.sin()math.cos())始终需要以弧度为单位的 Importing 值。此外,在math.log()中添加了可选的* base *参数,以使计算除e10以外的底数的对数变得更加容易。 (由 Raymond Hettinger 提供.)

  • 几个新的 POSIX 函数(getpgid()killpg()lchown()loadavg()major()makedev()minor()mknod())被添加到了os模块的posix模块中。 (由 Gustavo Niemeyer,Geert Jansen 和 Denis S. Otkidach 贡献.)

  • 现在,在os模块中,*stat()系列函数可以报告时间戳中的几分之一秒。这样的时间戳表示为浮点数,类似于time.time()返回的值。

在测试过程中,发现如果时间戳是 Float 的,则某些应用程序将break。为了兼容性,使用stat_result的 Tuples 接口时,时间戳将表示为整数。使用命名字段(Python 2.2 中首次引入的Function)时,时间戳记仍将表示为整数,除非调用os.stat_float_times()来启用浮点返回值:

>>> os.stat("/tmp").st_mtime
1034791200
>>> os.stat_float_times(True)
>>> os.stat("/tmp").st_mtime
1034791200.6335014

在 Python 2.4 中,默认设置将更改为始终返回浮点数。

只有当所有库在遇到浮点时间戳时都能正常工作,或者使用 TuplesAPI 时,应用程序开发人员才应启用此Function。如果使用该Function,则应在应用程序级别上激活该Function,而不是try逐个启用它。

  • optparse模块包含一个用于命令行参数的新解析器,该解析器可以将选项值转换为特定的 Python 类型,并将自动生成使用情况消息。有关更多详细信息,请参见以下部分。

  • 不推荐使用的旧的linuxaudiodev模块已被弃用,并添加了名为ossaudiodev的新版本。该模块被重命名是因为 OSS 声音驱动程序可以在 Linux 以外的平台上使用,并且该界面也已经进行了整理,并以各种方式进行了更新。 (由 Greg Ward 和 Nicholas FitzRoy-Dale 贡献.)

  • 新的platform模块包含许多函数,这些函数试图确定您所运行的平台的各种属性。有一些Function可以获取体系结构,CPU 类型,Windows OS 版本,甚至 Linux 发行版本。 (由马克·安德烈·伦堡贡献.)

  • 现在,由pyexpat模块提供的解析器对象可以选择缓冲字符数据,从而减少了对字符数据处理程序的调用,从而提高了性能。将解析器对象的buffer_text属性设置为True将启用缓冲。

  • sample(population, k)Function已添加到random模块。 * population 是包含总体元素的序列或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模块还获得了许多新Function:get_history_item()get_current_history_length()redisplay()

  • rexecBastion模块已被语句为无效,并且try导入它们将失败,并带有RuntimeError。new-style类提供了突破rexec提供的受限执行环境的新方法,并且没有人感兴趣修复它们或这样做。如果您的应用程序使用rexec,请重写它们以使用其他Function。

(使用 Python 2.2 或 2.1 不会使您的应用程序更安全,因为这些版本的rexec模块中存在已知的错误。要重复:如果您使用的是rexec,请立即停止使用它。)

  • rotor模块已被弃用,因为它认为用于加密的算法不安全。如果需要加密,请使用单独提供的多个 AES Python 模块之一。

  • shutil模块获得了move(src, dest)函数,该函数将文件或目录递归移动到新位置。

  • 对更高级的 POSIXsignal 处理的支持已添加到signal,但由于无法证明它无法跨平台可靠地工作而被再次删除。

  • socket模块现在支持超时。您可以在套接字对象上调用settimeout(t)方法以将超时设置为* t 秒。随后耗时超过 t *秒的套接字操作将中止并引发socket.timeout异常。

最初的超时实现是由 Tim O'Malley 执行的。 Michael Gilfix 将其集成到 Python socket模块中,并进行了冗长的审查。检入代码后,Guido van Rossum 重写了部分代码。 (这是实际的协作开发过程的一个很好的例子.)

  • 在 Windows 上,socket模块现在附带安全套接字层(SSL)支持。

  • C PYTHON_API_VERSION宏的值现在在 python 级别公开为sys.api_version。可以pass调用新的sys.exc_clear()函数清除当前异常。

  • 新的tarfile模块允许读取和写入 tar 格式的存档文件。 (由 LarsGustäbel 提供.)

  • 新的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.
>>>

该模块还包含一个实际实现 textwrap 策略的TextWrapper类。 TextWrapper类以及wrap()fill()函数都支持许多其他关键字参数,用于微调格式。有关详细信息,请查阅模块的文档。 (由 Greg Ward 提供.)

  • threadthreading模块现在具有配套模块dummy_threaddummy_threading,它们为不支持线程的平台提供了thread模块接口的无效实现。目的是pass在顶部放置以下代码来简化线程感知模块(依赖线程运行的模块):
try:
    import threading as _threading
except ImportError:
    import dummy_threading as _threading

在此示例中,使用_threading作为模块名称,以明确说明所使用的模块不一定是实际的threading模块。无论是否支持线程,代码都可以调用函数并使用_threading中的类,从而避免if语句并使代码更加清晰。这个模块不会神奇地使多线程代码在没有线程的情况下运行。await 另一个线程返回或执行某些操作的代码将永远挂起。

  • time模块的strptime()函数长期以来一直很烦人,因为它使用平台 C 库的strptime()实现,并且不同的平台有时会出现奇怪的错误。 Brett Cannon 提供了一个用纯 Python 编写的可移植实现,并且在所有平台上的行为都应相同。

  • 新的timeit模块有助于衡量执行 Python 代码段的时间。 timeit.py文件可以直接从命令行运行,或者模块的Timer类可以导入并直接使用。这是一个简短的示例,说明pass向其附加空 Unicode 字符串或使用unicode()函数将 8 位字符串转换为 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 接口,当从另一个线程访问小部件时,pass编组命令,将其传递到正确的线程并 await 结果,Tkinter现在将自动避免这种情况。其他接口无法自动处理,但是Tkinter现在会在此类访问中引发异常,以便您至少可以找出问题所在。有关此更改的详细说明,请参见https://mail.python.org/pipermail/python-dev/2002-December/031107.html。 (由 Martin vonLöwis 实施.)

  • pass_tkinter调用 Tcl 方法不再仅返回字符串。相反,如果 Tcl 返回其他对象,则将这些对象转换为它们的 Python 等效对象(如果存在),或者如果不存在 Python 等效对象,则将它们包装为_tkinter.Tcl_Obj对象。可以passtkapp对象的wantobjects()方法来控制此行为。

passTkinter模块使用_tkinter时(就像大多数 Tkinter 应用程序一样),此Function始终处于激活状态。它不会引起兼容性问题,因为 Tkinter 总是会尽可能将字符串结果转换为 Python 类型。

如果发现任何不兼容性,则可以pass在创建第一个tkapp对象之前将Tkinter模块中的wantobjects变量设置为 false 来恢复旧的行为。

import Tkinter
Tkinter.wantobjects = 0

由此更改引起的任何损坏都应报告为错误。

  • UserDict模块具有一个新的DictMixin类,该类定义了已经具有最小 Map 接口的类的所有字典方法。这大大简化了需要替换为字典的类,例如shelve模块中的类。

每当该类定义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 提供.)

  • 现在,pass为 DOM 节点的toxml()toprettyxml()方法提供可选的编码参数,xml.dom.minidom中的 DOM 实现可以生成特定编码的 XML 输出。

  • xmlrpclib模块现在支持 XML-RPC 扩展,用于处理 nil 数据值,例如 Python 的None。在解组 XML-RPC 响应时始终支持 Nil 值。要生成包含None的请求,您必须在创建Marshaller实例时为* allow_none *参数提供一个真值。

  • 新的DocXMLRPCServer模块允许编写自文档的 XML-RPC 服务器。以演示模式运行它(作为程序)以查看其运行情况。将 Web 浏览器指向 RPC 服务器会生成 pydoc 样式的文档;将 xmlrpclib 指向服务器允许调用实际方法。 (由 Brian Quinlan 提供.)

  • 添加了对国际化域名(RFC 3454、3490、3491 和 3492)的支持。 “ idna”编码可用于在 Unicode 域名和该名称的 ASCII 兼容编码(ACE)之间进行转换。

>{}>{}> u"www.Alliancefrançaise.nu".encode("idna")
'www.xn--alliancefranaise-npb.nu'

socket模块也已扩展为在将 Unicode 主机名传递给 C 库之前将其透明转换为 ACE 版本。处理诸如httplibftplib之类的主机名的模块也支持 Unicode 主机名。 httplib还使用 ACE 版本的域名发送 HTTP HostHeaders。 urllib支持具有非 ASCII 主机名的 Unicode URL,只要 URL 的path部分仅是 ASCII。

为了实现此更改,已添加了stringprep模块,mkstringprep工具和punycode编码。

Date/Time Type

适用于表示时间戳的日期和时间类型已添加为datetime模块。这些类型不支持不同的 calendar 或许多精美Function,仅坚持表示时间的基础。

三种主要类型是:date,分别代表日,月和年; time,由小时,分钟和秒组成;和datetime,其中包含datetime的所有属性。还有一个timedelta类代表两个时间点之间的差异,时区逻辑由继承自抽象tzinfo类的类实现。

您可以pass向适当的构造函数提供关键字参数来创建datetime的实例,例如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()方法允许修改datedatetime实例的一个或多个字段,并返回一个新实例:

>>> 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()相同)。 datedatetime实例可以相互减去,然后添加到timedelta实例中。缺少的最大Function是,没有标准库支持解析字符串并返回datedatetime

有关更多信息,请参阅模块的参考文档。 (由蒂姆·彼得斯贡献.)

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

然后,pass调用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 SIGReader 的建议。

Pymalloc:专门的对象分配器

Pymalloc 是由 Vladimir Marangozov 编写的专用对象分配器,它是 Python 2.1 中新增的一项Function。 Pymalloc 旨在比系统malloc()更快,并且对于 Python 程序的典型分配模式而言,具有较少的内存开销。分配器使用 C 的malloc()函数获取较大的内存池,然后从这些池执行较小的内存请求。

在 2.1 和 2.2 中,pymalloc 是一项实验性Function,默认情况下未启用。您必须在 configure 脚本中提供--with-pymalloc选项,才能在编译 Python 时显式启用它。在 2.3 版中,pymalloc 进行了进一步的增强,默认情况下已启用;您必须提供--without-pymalloc才能将其禁用。

对于使用 Python 编写的代码而言,此更改是透明的。但是,pymalloc 可能会暴露 C 扩展中的错误。 C 扩展模块的作者应在启用 pymalloc 的情况下测试其代码,因为某些不正确的代码可能会在运行时导致核心转储。

有一个特别常见的错误会导致问题。 Python 的 C API 中有许多内存分配函数,它们以前只是 C 库的malloc()free()的别名,这意味着如果您不小心调用了不匹配的函数,该错误将不会引起注意。启用对象分配器后,这些函数不再是malloc()free()的别名,并且调用错误的函数来释放内存可能会导致核心转储。例如,如果使用PyObject_Malloc()分配内存,则必须使用PyObject_Free()而不是free()释放内存。 Python 附带的一些模块与此不符,必须加以修复;毫无疑问,会有更多的第三方模块会出现相同的问题。

作为此更改的一部分,用于分配内存的混乱的多个接口已合并为两个 API 系列。一个家族分配的内存一定不能被另一个家族的Function操纵。有一个系列用于分配内存块,另一类Function专门用于分配 Python 对象。

由于 Tim Peters 的大量工作,2.3 版中的 pymalloc 还提供了调试Function,以捕获扩展模块和解释器本身中的内存覆盖和释放的空余空间。要启用此支持,请使用--with-pydebug运行 configure 来编译 Python 解释器的调试版本。

为了帮助扩展编写者,将头文件Misc/pymemcompat.h与源一起分发到 Python 2.3,该文件允许 Python 扩展使用 2.3 接口进行内存分配,同时针对自 1.5.2 版以来的任何版本的 Python 进行编译。您可以从 Python 的源代码发行版中复制文件,并将其与扩展源 Binding 在一起。

See also

Build 和 C API 的更改

对 Python 的构建过程和 C API 的更改包括:

  • 垃圾收集所使用的循环检测实现已被证明是稳定的,因此现在已被强制执行。没有它,您将无法再编译 Python,并且删除了--with-cycle-gc切换到 configure 的Function。

  • 现在,可以选择在运行 Python 的 configure 脚本时提供--enable-shared来将 Python 构建为共享库(libpython2.3.so)。 (由 Ondrej Palkovsky 提供.)

  • 现在不推荐使用DL_EXPORTDL_IMPORT宏。现在应该使用新的宏PyMODINIT_FUNC语句 Python 扩展模块的初始化函数,而 Python 内核通常将使用PyAPI_FUNCPyAPI_DATA宏。

  • pass向 configure 脚本提供--without-doc-strings,可以为内置函数和模块编译没有任何文档字符串的解释器。这使 Python 可执行文件缩小了大约 10%,但这也意味着您无法获得有关 Python 内置程序的帮助。 (由 Gustavo Niemeyer 提供.)

  • 现在不推荐使用PyArg_NoArgs()宏,并且应该更改使用该宏的代码。对于 Python 2.2 及更高版本,方法定义表可以指定METH_NOARGS标志,表示没有参数,然后可以删除参数检查。如果与 2.2 之前版本的 Python 的兼容性很重要,则代码可以改用PyArg_ParseTuple(args, ""),但这会比使用METH_NOARGS慢。

  • PyArg_ParseTuple()接受各种大小的无符号整数的新格式字符:B表示unsigned charH表示unsigned short intI表示unsigned intK表示unsigned long long

  • 添加了一个新FunctionPyObject_DelItemString(mapping, char *key)作为PyObject_DelItem(mapping, PyString_New(key))的简写。

  • 现在,文件对象以不同的方式 Management 其内部字符串缓冲区,并在需要时以指数方式增加它。这导致Lib/test/test_bufio.py中的基准测试速度大大提高(根据一项测量,从 57 秒提高到 1.7 秒)。

  • 现在可以pass在方法的PyMethodDef结构中设置METH_CLASSMETH_STATIC标志来为 C 扩展类型定义类和静态方法。

  • Python 现在包括 Expat XML 解析器源代码的副本,从而消除了对系统版本或 Expat 本地安装的任何依赖。

  • 如果在扩展中动态分配类型对象,则应注意与__module__name属性有关的规则发生了变化。总之,您将需要确保类型的字典包含'__module__'键;将模块名称作为类型名称的一部分,直到最后一个时期将不再具有期望的效果。有关更多详细信息,请阅读 API 参考文档或源。

Port-Specific Changes

使用 EMX 运行时环境对 IBM OS/2 端口的支持已合并到主要的 Python 源代码树中。 EMX 是 OS/2 系统 API 上的 POSIX 仿真层。用于 EMX 的 Python 端口试图支持 EMX 运行时公开的所有类似 POSIX 的Function,并且大多数情况下都是成功的。 fork()fcntl()受基础仿真层的限制。使用 IBM Visual Age 编译器的标准 OS/2 端口,还支持区分大小写的导入语义,这是将 EMX 端口集成到 CVS 中的一部分。 (由安德鲁·麦金太尔贡献.)

在 MacOS 上,大多数工具箱模块已被弱链接以提高向后兼容性。这意味着,如果当前 os 版本缺少单个例程,模块将不再无法加载。而是调用缺少的例程将引发异常。 (由杰克·詹森贡献.)

在 Python 源发行版的Misc/RPM/目录中找到的 RPM 规范文件已更新为 2.3. (由 Sean Reifschneider 提供.)

Python 现在支持的其他新平台包括 AtheOS(http://atheos.cx/),GNU/Hurd 和 OpenVMS。

其他更改和修复

像往常一样,在源代码树中还分散了许多其他改进和错误修正。在 CVS 更改日志中进行搜索后发现,在 Python 2.2 和 2.3 之间修复了 523 个补丁,并修复了 514 个错误。这两个数字可能都被低估了。

一些更显着的变化是:

  • 如果设置了 PYTHONINSPECT环境变量,则在运行 Python 程序后,Python 解释器将进入交互式提示,就像使用-i选项调用了 Python 一样。环境变量可以在运行 Python 解释器之前设置,也可以由 Python 程序在其执行过程中设置。

  • regrtest.py脚本现在提供了一种允许“除* foo *之外的所有资源”的方法。现在,传递给-u选项的资源名称可以加上连字符('-')前缀,以表示“删除此资源”。例如,选项“ -uall,-bsddb”可用于启用除bsddb之外的所有资源。

  • 现在,用于构建文档的工具可在 Cygwin 和 Unix 下使用。

  • SET_LINENO操作码已被删除。回到时间的迷雾中,需要此操作码来产生回溯中的行号并支持跟踪Function(例如pdb)。从 Python 1.5 开始,回溯中的行号是使用与“ python -O”一起使用的另一种机制来计算的。对于 Python 2.3,Michael Hudson 实现了类似的方案来确定何时调用 trace 函数,从而完全消除了对SET_LINENO的需要。

除了在没有-O的情况下运行 Python 会稍微加快速度之外,很难检测到与 Python 代码之间的任何差异。

访问框架对象f_lineno字段的 C 扩展应该调用PyCode_Addr2Line(f->f_code, f->f_lasti)。这将具有使代码在 Python 早期版本中的“ python -O”下按需工作的附加效果。

一项不错的新Function是,跟踪函数现在可以分配给框架对象的f_lineno属性,从而更改将在下一步执行的行。利用此新Function,已将jump命令添加到pdb调试器。 (由 Richie Hindle 实施.)

移植到 Python 2.3

本部分列出了先前描述的更改,可能需要更改您的代码:

  • yield现在始终是关键字;如果在代码中将其用作变量名,则必须选择其他名称。

  • 对于字符串* X Y ,如果 X *长于一个字符,则X in Y现在可以使用。

  • 现在,当字符串或浮点数太大而无法容纳整数时,int()类型的构造函数将返回一个长整数而不是引发OverflowError

  • 如果您的 Unicode 字符串包含 8 位字符,则必须pass在文件顶部添加 Comments 来语句文件的编码(UTF-8,Latin-1 或其他格式)。有关更多信息,请参见第PEP 263:源代码编码节。

  • pass_tkinter调用 Tcl 方法不再仅返回字符串。相反,如果 Tcl 返回其他对象,则将这些对象转换为它们的 Python 等效对象(如果存在),或者如果不存在 Python 等效对象,则将它们包装为_tkinter.Tcl_Obj对象。

  • 大型八进制和十六进制 Literals(例如0xffffffff)现在触发FutureWarning。目前,它们以 32 位数字存储并导致负值,但是在 Python 2.4 中,它们将成为正长整数。

有几种方法可以纠正此警告。如果您确实需要一个正数,只需在 Literals 末尾添加L即可。如果您try获取设置了低位的 32 位整数,并且以前使用过~(1 << 31)之类的表达式,那么从设置所有位开始并清除所需的高位可能是最清晰的方法。例如,要仅清除最高位(位 31),可以写入0xffffffffL &~(1L<<31)

  • 您不能再pass分配给__debug__来禁用 assert。

  • Distutils setup()函数获得了各种新的关键字参数,例如* depends *。如果传递了未知的关键字,则 Distutils 的旧版本将中止。一种解决方案是检查setup.py中是否存在新的get_distutil_options()函数,并且仅将新关键字与支持它们的 Distutils 版本一起使用:

from distutils import core

kw = {'sources': 'foo.c', ...}
if hasattr(core, 'get_distutil_options'):
    kw['depends'] = ['foo.h']
ext = Extension(**kw)
  • 现在使用None作为变量名将产生SyntaxWarning警告。

  • 现在,Python 随附的模块定义的扩展类型名称包含模块和类型名称前的'.'

Acknowledgements

作者在此感谢以下人员对本文的各种草案提供的建议,更正和帮助:杰夫·鲍尔,西蒙·布鲁宁,布雷特·坎农,迈克尔·彻姆赛德,安德鲁·达尔克,斯科特·大卫·丹尼尔斯,弗雷德·德雷克, David Fraser,Kelly Gerber,Raymond Hettinger,Michael Hudson,Chris Lambert,Detlef Lannert,Martin vonLöwis,Andrew MacIntyre,Lalo Martins,Chad Netzer,Gustavo Niemeyer,Neal Norwitz,Hans Nowak,Chris Reedy,Francesco Ricciardi,Vinay Sajip Schemenauer,Roman Suzi,Jason Tishler,Just van Rossum。