What’s New in Python 2.3

作者:上午。 Kuchling

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

Python 2.3的主要主题是抛光2.2中添加的一些功能,为核心语言添加了各种小但有用的增强功能,并扩展了标准库。在以前的版本中引入的新对象模型已经从18个月的错误修正和优化努力中获益,改进了新式类的性能。添加了一些新的内建函数,例如sum()enumerate()操作符中的in“ab” “abc”返回True)。

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

本文不试图提供新功能的完整规范,而是提供了一个方便的概述。有关详细信息,请参阅Python 2.3的文档,例如Python库参考和Python参考手册。如果您想了解完整的实现和设计理由,请参阅PEP了解特定的新功能。

PEP 218: A Standard Set Datatype

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

也可以看看

PEP 218 - 添加内建集对象类型
PEP由Greg V. Wilson写。由Greg V. Wilson,Alex Martelli和GvR实施。

PEP 255: Simple Generators

在Python 2.2中,添加生成器作为可选功能,通过 __ future __ 导入 生成器指令。在2.3生成器不再需要特别启用,并且现在总是存在;这意味着yield现在总是一个关键字。本节的其余部分是从“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语句。yieldreturn语句之间的巨大差异是,在达到yield时,生成器的执行状态被暂停,并且保留局部变量。在下一次调用生成器的.next()方法时,函数将在yield语句之后立即恢复执行。(由于复杂的原因,在try ... finallytry块中不允许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

You could equally write for i in generate_ints(5), or a,b,c = generate_ints(3).

在生成器函数内部,return语句只能在没有值的情况下使用,并且表示值的队列的结束;之后生成器不能返回任何进一步的值。具有诸如返回 5等值的return是生成器函数内的语法错误。生成器结果的结束也可以通过手动提高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 $国际象棋棋盘上,使得没有女王威胁另一个棋子)和骑士之旅(一个骑士到一个$ 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的接口的一个新特征是生成器的状态被表示为一个具体的对象(迭代器),可以传递到其他函数或存储在数据结构中。

也可以看看

PEP 255 - 简单生成器
作者:Neil Schemenauer,Tim Peters,Magnus Lie Hetland。主要由Neil Schemenauer和Tim Peters执行,以及Python实验室团队的其他修复。

PEP 263: Source Code Encodings

Python源文件现在可以声明为处于不同的字符集编码。通过在源文件的第一行或第二行中包含特殊格式的注释来声明编码。例如,可以用以下语句声明UTF-8文件:

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

没有这样的编码声明,所使用的默认编码是7位ASCII。执行或导入包含具有8位字符的字符串字面值且没有编码声明的模块将导致Python 2.3发出DeprecationWarning信号;在2.4这将是一个语法错误。

编码声明只影响Unicode字符串字面值,它将使用指定的编码转换为Unicode。请注意,Python标识符仍仅限于ASCII字符,因此您不能使用使用通常字母数字以外的字符的变量名称。

也可以看看

PEP 263 - 定义Python源代码编码
作者:Marc-AndréLemburg和Martin vonLöwis;由Suzuki Hisao和Martin vonLöwis执行。

PEP 273: Importing Modules from ZIP Archives

新的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文件来修改归档,这意味着如果ZIP归档不包含*.pyc文件,导入可能会相当缓慢。

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

也可以看看

PEP 273 - 从Zip档案库导入模块
作者James C. Ahlstrom,他也提供了一个实现。Python 2.3遵循 PEP 273中的规范,但使用由Just van Rossum编写的使用 PEP 302有关新导入钩子的说明,请参阅PEP 302: New Import Hooks一节。

PEP 277: Unicode file name support for Windows NT

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

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

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

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

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

也可以看看

PEP 277 - Windows NT的Unicode文件名支持
作者:Neil Hodgson;由Neil Hodgson,Martin vonLöwis和Mark Hammond执行。

PEP 278: Universal Newline Support

目前使用的三个主要操作系统是Microsoft Windows,Apple的Macintosh OS和各种Unix衍生产品。跨平台工作的一个小的刺激是,这三个平台都使用不同的字符来标记文本文件中的行的末尾。Unix使用换行符(ASCII字符10),MacOS使用回车符(ASCII字符13),Windows使用回车符的双字符序列加换行符。

Python的文件对象现在可以支持除了由运行Python的平台遵循的结束约定。使用模式'U''rU'打开文件将打开一个文件,以便在universal newlines模式下读取。All three line ending conventions will be translated to a '\n' in the strings returned by the various file methods such as read() and readline().

当导入模块和使用execfile()函数执行文件时,也使用通用换行符支持。这意味着Python模块可以在所有三个操作系统之间共享,而不需要转换行结束。

在运行Python的configure脚本时,通过指定--without-universal-newlines开关来编译Python时,可以禁用此功能。

也可以看看

PEP 278 - 通用Newline支持
由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

也可以看看

PEP 279 - 枚举()内建函数
由Raymond D. Hettinger撰写和实施。

PEP 282: The logging Package

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

Logger类是主类。大多数应用程序代码将处理一个或多个Logger对象,每个对象由应用程序的特定子系统使用。每个Logger由一个名称标识,并使用.作为组分分离器。例如,您可能有Logger实例名为serverserver.authserver.network后两个实例位于层次结构中server下。This means that if you turn up the verbosity for server or direct server messages to a different handler, the changes will also apply to records logged to server.auth and 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, ...) t6> ...)

还有一个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')
 ...

日志记录通常沿层次结构向上传播,因此serverroot也可看到记录到server.auth的消息,但Logger可以通过将其propagate属性设置为False来防止此情况发生。

还有可以自定义的logging包提供的更多类。当告诉Logger实例记录消息时,它会创建一个发送到任意数量的不同Handler实例的LogRecord实例。记录器和处理程序也可以附加过滤器列表,每个过滤器可以使LogRecord被忽略,或者可以在传递记录之前修改记录。当它们最终输出时,通过Formatter类将LogRecord实例转换为文本。所有这些类都可以被你自己专门写的类替换。

通过所有这些功能,logging包应该为最复杂的应用程序提供足够的灵活性。这只是其功能的不完整概述,因此请参阅软件包的参考文档以了解所有详细信息。读取 PEP 282也将有所帮助。

也可以看看

PEP 282 - 记录系统
作者:Vinay Sajip和Trent Mick;由Vinay Sajip执行。

PEP 285: A Boolean Type

一个布尔类型被添加到Python 2.3。将两个新常数添加到__builtin__模块,TrueFalseTrueFalse常量添加到Python 2.2.1的内置函数中,但是2.2.1版本只是设置为1和0的整数值,aren不同类型。)

此新类型的类型对象名为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语句中的表达式始终计算为布尔运算结果。Python不是这个严格的,永远不会,因为 PEP 285明确说。这意味着您仍然可以使用if语句中的任何表达式,甚至计算到列表或元组或某些随机对象的表达式。布尔类型是int类的子类,因此使用布尔的算术仍然有效。

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

To sum up True and False in a sentence: they’re alternative ways to spell the integer values 1 and 0, with the single difference that str() and repr() return the strings 'True' and 'False' instead of '1' and '0'.

也可以看看

PEP 285 - 添加布尔类型
由GvR编写和实施。

PEP 293: Codec Error Handling Callbacks

当将Unicode字符串编码为字节字符串时,可能遇到不可编码的字符。到目前为止,Python允许将错误处理指定为“strict”(提高UnicodeError),“忽略”(跳过字符)或“replace”(使用输出字符串中的问号) ,其中“strict”是默认行为。可能希望指定这种错误的替代处理,例如将XML字符引用或HTML实体引用插入到转换的字符串中。

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

使用此框架实现了两个额外的错误处理程序:“backslashreplace”使用Python反斜杠引用来表示不可编辑的字符,“xmlcharrefreplace”发出XML字符引用。

也可以看看

PEP 293 - 编解码器错误处理回调
由WalterDörwald撰写和实施。

PEP 301: Package Index and Metadata for Distutils

支持长期请求的Python目录在2.3中首次出现。

目录的核心是新的Distutils 寄存器命令。运行python setup.py tt> 注册将收集描述包的元数据,如名称,版本,维护者,描述&c。,并将其发送到中央目录服务器。生成的目录可从https://pypi.python.org/pypi获取。

为了使目录更有用,向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 注册 - list-classifiers t4 >

也可以看看

PEP 301 - Distutils的软件包索引和元数据
由Richard Jones撰写和实施。

PEP 302: New Import Hooks

虽然自从ihooks模块在Python 1.3中引入以来就可以编写自定义的导入钩子,但是没有人真正对它感到满意,因为编写新的导入钩子是困难和混乱的。已经有各种提议的替代方案,例如imputiliu模块,但是它们都没有得到很多接受,并且它们都不容易从C代码中使用。

PEP 302借用其前辈的想法,特别是从Gordon McMillan的iu模块。三个新项目添加到sys模块:

  • sys.path_hooks是可调用对象的列表;最常见的是他们会上课。每个可调用都接受一个包含路径的字符串,并且返回一个导入器对象,该对象将处理从此路径导入的内容或引发ImportError异常,如果它无法处理此路径。
  • sys.path_importer_cache缓存每个路径的导入器对象,因此sys.path_hooks只需要为每个路径遍历一次。
  • sys.meta_path是在检查sys.path之前将被遍历的导入器对象的列表。此列表最初为空,但用户代码可以向其中添加对象。附加的内建和冻结模块可以通过添加到此列表中的对象导入。

导入器对象必须有一个方法,find_module(fullname, path = None)fullname将是一个模块或程序包名称,例如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

也可以看看

PEP 302 - 新的导入挂钩
作者:Just van Rossum和Paul Moore。由Just van Rossum执行。

PEP 305: Comma-separated Files

逗号分隔的文件是经常用于从数据库和电子表格导出数据的格式。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
由Kevin Altis,Dave Cole,Andrew McNamara,Skip Montanaro,Cliff Wells撰写和实施。

PEP 307: Pickle Enhancements

在2.3开发周期期间,picklecPickle模块受到一些关注。在2.2中,新式课程可以毫无困难地进行酸洗,但他们不是非常紧凑的酸洗; PEP 307引用了一个简单的例子,其中一个新式类导致一个经过酸洗的字符串比经典类的长三倍。

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

Unpickling不再被认为是一个安全的操作。2.2的pickle提供了用于防止不安全类被取消绑定的钩子(具体来说,是一个__safe_for_unpickling__属性),但是这些代码都没有经过审计,翻出2.3。您不应该取消对任何版本的Python中的不受信任的数据。

为了减少新式类的酸洗开销,使用三种特殊方法添加了用于定制酸洗的新界面:__getstate__()__setstate__()__getnewargs__()有关这些方法的完整语义,请参阅 PEP 307

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

也可以看看

PEP 307 - 对pickle协议的扩展
由Guido van Rossum和Tim Peters编写和实施。

Extended Slices

从Python 1.4开始,切片语法支持可选的第三个“step”或“stride”参数。For example, these are all legal Python syntax: 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]

扩展切片不是这么灵活。当分配给扩展slice时,语句右侧的列表必须包含与它替换的slice相同数量的项:

>>> 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)元组,可直接传递到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一致,其中intstr等,经历了相同的更改。

Other Language Changes

这里是Python 2.3对核心Python语言所做的所有更改。

  • yield语句现在总是一个关键字,如本文档PEP 255: Simple Generators中所述。

  • 添加了一个新的内建函数enumerate(),如本文档的PEP 279: enumerate()中所述。

  • Two new constants, True and False were added along with the built-in bool type, as described in section PEP 285: A Boolean Type of this document.

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

  • 内建类型现在支持扩展切片语法,如本文档的Extended Slices部分所述。

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

  • 时,用于在列表前面插入list.insert(pos, value) pos为负。现在,行为已更改为与切片索引一致,因此,当pos为-1时,该值将插入到最后一个元素之前,依此类推。

  • list.index(value), which searches for value within the list and returns its index, now takes optional start and stop arguments to limit the search to only part of the list.

  • 字典有一个新方法,pop(key [, * default *]),返回对应t3>并从字典中删除该键/值对。如果字典中没有请求的键,则返回默认值,如果没有指定,则返回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__标志,因此您无法再通过分配__debug__来禁用断言。使用-O开关运行Python仍然会生成不执行任何断言的代码。

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

    >>> import types
    >>> m = types.ModuleType('abc','docstring')
    >>> m
    <module 'abc' (built-in)>
    >>> m.__doc__
    'docstring'
    
  • 添加了新的警告,PendingDeprecationWarning以指示正在被弃用的进程中的功能。默认情况下,将打印警告要检查将来是否会被弃用的功能,请在命令行上提供-Walways::PendingDeprecationWarning::,或使用warnings.filterwarnings()

  • 已开始在提高 “错误 发生”时弃用基于字符串的异常的过程。提高字符串将触发PendingDeprecationWarning

  • 使用None作为变量名称现在将导致SyntaxWarning警告。在未来版本的Python中,None可能最终成为关键字。

  • 不再需要在Python 2.1中引入的文件对象的xreadlines()方法,因为文件现在表现为自己的迭代器。xreadlines()最初是作为一个更快的方式循环文件中的所有行,但现在你可以简单地写for t4> in file_obj文件对象还具有新的只读encoding属性,它提供文件使用的编码;写入文件的Unicode字符串将使用给定的编码自动转换为字节。

  • new-style类使用的方法解析顺序已经改变,但是如果你有一个真正复杂的继承层次结构,你只会注意到差别。经典类不受此更改的影响。Python 2.2最初使用一个类的祖先的拓扑排序,但2.3现在使用如在“Dylan的单调超类线性化”的论文中描述的C3算法。要了解此更改的动机,请阅读Michele Simionato的文章“Python 2.3方法解析顺序”,或者读取python-dev上的线程,从开始https://mail.python .org / pipermail / python-dev / 2002-October / 029035.htmlSamuele Pedroni首先指出了问题,并通过编码C3算法实现了修复。

  • Python通过在执行N个字节码后在线程之间切换来运行多线程程序。N的默认值已从10个字节码增加到100个字节码,通过减少交换开销来加速单线程应用程序。一些多线程应用程序可能会遇到较慢的响应时间,但很容易通过使用sys.setcheckinterval(N)将限制设置为较低的数字来修复。可以使用新的sys.getcheckinterval()函数检索限制。

  • 一个小的但深远的变化是,由Python包含的模块定义的扩展类型的名称现在包含模块和'.'None例如,在Python 2.2中,如果你创建了一个套接字并打印了它的__class__,你会得到这个输出:

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

    在2.3,你得到这:

    >>> s.__class__
    <type '_socket.socket'>
    
  • 旧样式类和新样式类之间的一个已知不兼容性已被删除:现在可以分配到新样式类的__name____bases__属性。对于可以分配给与分配给实例的__class__属性相关的行的__bases__有一些限制。

String Changes

  • in操作符号现在对字符串有不同的作用。以前,当评估X Y其中X/ t5>是字符串,X只能是单个字符。现在改变了; X可以是任何长度的字符串,并且 Y中的X True如果XY的子字符串。如果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()字符串方法现在接受startend参数的负数。

  • 另一个新的字符串方法是zfill(),最初是string模块中的函数。zfill()在左侧填充一个带有零的数字字符串,直到它为指定的宽度。注意,%操作符比zfill()更灵活和强大。

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

    (供稿人:WalterDörwald。)

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

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

Optimizations

  • 新式类实例的创建已经做得更快;他们现在比经典类更快了!
  • 列表对象的sort()方法已被Tim Peters广泛地重写,并且实现速度明显更快。
  • 大长整数的乘法现在要快得多,这要归功于Karatsuba乘法的实现,Karatsuba乘法是一种比小学乘法算法所需的O(n * n)更好的算法。(由克里斯托弗·克雷格的原始补丁,由蒂姆·彼得斯大量修改。)
  • SET_LINENO操作码现在已不存在。这可能提供一个小的速度增加,这取决于你的编译器的特性。有关更多说明,请参阅Other Changes and Fixes一节。(由Michael Hudson删除。)
  • xrange() objects now have their own iterator, making for i in xrange(n) slightly faster than for i in range(n). (补丁:Raymond Hettinger。)
  • 在各种热点中进行了许多小的重新排列以提高性能,例如内联函数或删除一些代码。(主要由GvR实施,但很多人已经贡献了单一的变化。)

2.3优化的最终结果是Python 2.3运行pystone基准测试的速度比Python 2.2快25%。

New, Improved, and Deprecated Modules

像往常一样,Python的标准库收到了一些增强和错误修复。这里是最显着的变化的部分列表,按模块名称按字母顺序排序。请参阅源树中的Misc/NEWS文件以获取更完整的更改列表,或查看CVS日志以了解所有详细信息。

  • array模块现在支持使用'u'数组现在还支持使用+=赋值操作符来添加另一个数组的内容,并且使用*=赋值操作符来重复数组。(由Jason Orendorff提供)

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

    旧版本的模块已重命名为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的配置(由罗伯特·韦伯贡献)。

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

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

  • The getopt module gained a new function, gnu_getopt(), that supports the same arguments as the existing getopt() function but uses GNU-style scanning mode. 一旦遇到非选项参数,现有的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'])
    

    (供稿人:PeterÅstrand。)

  • grppwdresource模块现在返回增强的元组:

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

  • 新的heapq模块包含一个堆队列算法的实现。堆是类似数组的数据结构,其保持项目以部分排序的顺序,使得对于每个索引k堆[k] ; = t> heap [2 * k + 1]heap [k] &lt; = heap [2 * k + 2]这使得它快速删除最小的项目,并且插入一个新的项目,同时保持heap属性是O(lg n)。(有关优先级队列数据结构的详细信息,请参阅https://xlinux.nist.gov/dads//HTML/priorityque.html)。

    heapq模块提供heappush()heappop()功能,用于添加和删除项目,同时将堆属性保持在其他可变的Python序列类型。这里有一个使用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提供。)

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

  • imaplib模块现在支持基于SSL的IMAP。(供稿人:Piers Lauder和Tino Lange。)

  • itertools包含许多用于迭代器的有用函数,受ML和Haskell语言提供的各种函数的启发。For example, itertools.ifilter(predicate, iterator) returns all elements in the iterator for which the function predicate() returns True, and itertools.repeat(obj, N) returns obj N times. 模块中有许多其他功能;有关详细信息,请参阅软件包的参考文档。(由Raymond Hettinger提供)

  • math模块中的两个新函数,degrees(rads)radians(degs)在弧度和度之间转换。math模块中的其他函数(如math.sin()math.cos())始终需要以弧度表示的输入值。此外,向math.log()中添加了可选的基本参数,以便更容易计算e10(由Raymond Hettinger提供)

  • Several new POSIX functions (getpgid(), killpg(), lchown(), loadavg(), major(), makedev(), minor(), and mknod()) were added to the posix module that underlies the os module. (由Gustavo Niemeyer,Geert Jansen和Denis S.Otkidach。)

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

    在测试期间,发现如果时间戳是浮动的,一些应用程序将中断。为了兼容性,当使用stat_result的tuple接口时,时间戳将被表示为整数。当使用命名字段(Python 2.2中首次引入的特性)时,时间戳仍然表示为整数,除非调用os.stat_float_times()以启用float返回值:

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

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

    应用程序开发人员只有在其所有的库在遇到浮点时间戳时正常工作,或者如果他们使用tuple API时才应该启用此功能。如果使用,应在应用程序级别上激活功能,而不是尝试在每次使用的基础上启用它。

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

  • 旧的和永远不会记录的linuxaudiodev模块已被弃用,并且添加了名为ossaudiodev的新版本。该模块被重命名,因为OSS声音驱动程序可以在除Linux以外的平台上使用,并且界面也以各种方式进行了整理和更新。(供稿:Greg Ward和Nicholas FitzRoy-Dale。)

  • 新的platform模块包含许多函数,尝试确定您运行的平台的各种属性。有一些功能用于获取架构,CPU类型,Windows操作系统版本,甚至Linux发行版本。(供稿人:Marc-AndréLemburg。)

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

  • 样本(群体, 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模块现在使用新的算法,Mersenne Twister,在C中实现。它比以前的算法更快,更广泛地研究。

    (所有更改由Raymond Hettinger提供。)

  • readline模块还获得了一些新函数:get_history_item()get_current_history_length()redisplay()

  • rexecBastion模块已声明为死亡,并尝试导入它们将失败,并显示RuntimeError新式类提供了新的方法来突破由rexec提供的受限执行环境,没有人有兴趣修复它们或时间这样做。如果您有使用rexec的应用程序,请将其重写以使用其他格式。

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

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

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

  • 支持更高级的POSIX信号处理被添加到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可以通过调用新的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.
    >>>
    

    该模块还包含实际实现文本包装策略的TextWrapper类。TextWrapper类和wrap()fill()函数支持一些额外的关键字参数以微调格式;有关详细信息,请参阅模块的文档。(由Greg Ward提供)

  • threadthreading模块现在具有辅助模块,dummy_threaddummy_threading thread模块的接口,用于不支持线程的平台。目的是通过在顶部放置以下代码来简化线程感知模块(不要依赖线程来运行):

    try:
        import threading as _threading
    except ImportError:
        import dummy_threading as _threading
    

    在此示例中,_threading用作模块名称,以表明正在使用的模块不一定是实际的threading模块。代码可以调用函数并在_threading中使用类,无论是否支持线程,避免使用if语句并使代码稍微清晰些。这个模块不会魔法地使多线程代码运行没有线程;等待另一个线程返回或做某事的代码将会永远挂起。

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

  • 新的timeit模块有助于测量Python代码片段执行的时间。timeit.py文件可以直接从命令行运行,或者模块的Timer类可以直接导入和使用。这里有一个简短的例子,通过将一个空的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接口,Tkinter现在将通过编组命令,将其传递到正确的线程并等待结果,从不同的线程访问窗口小部件时自动避免这种情况。其他接口不能自动处理,但Tkinter现在将引发这种访问的异常,以便您至少可以找到该问题。有关此更改的详细说明,请参阅https://mail.python.org/pipermail/python-dev/2002-December/031107.html(由Martin vonLöwis执行。)

  • 通过_tkinter调用Tcl方法不再仅返回字符串。相反,如果Tcl返回其他对象,那么如果没有Python对等存在,那么这些对象将转换为等价的Python对象(如果存在)或使用_tkinter.Tcl_Obj对象包装。此行为可以通过tkapp对象的wantobjects()方法控制。

    当通过Tkinter模块使用_tkinter时(大多数Tkinter应用程序将会),此功能总是被激活。它不应该导致兼容性问题,因为Tkinter将总是将字符串结果转换为Python类型尽可能。

    如果发现任何不兼容性,可以通过在创建第一个tkapp对象之前将Tkinter模块中的wantobjects变量​​设置为false, 。

    import Tkinter
    Tkinter.wantobjects = 0
    

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

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

    每当类定义__getitem__()__setitem__()__delitem__(),则添加作为超类的mix-in提供了完整的字典接口,和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提供)

  • xml.dom.minidom中的DOM实现现在可以通过向toxml()toprettyxml() DOM节点的方法。

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

  • 新的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主机名透明地转换为ACE版本,然后将它们传递到C库。处理主机名(如httplibftplib)的模块也支持Unicode主机名; httplib也使用ACE版本的域名发送HTTP Host标头。urllib支持使用非ASCII主机名的Unicode网址,只要网址的path部分仅为ASCII。

    要实施此更改,已添加stringprep模块,mkstringprep工具和punycode编码。

Date/Time Type

适用于表示时间戳的日期和时间类型作为datetime模块添加。类型不支持不同的日历或许多奇特的功能,只是坚持代表时间的基础。

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

您可以通过向适当的构造函数提供关键字参数来创建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实例中。最大的缺失功能是没有标准库支持解析字符串并返回datedatetime

有关更多信息,请参阅模块的参考文档。(由Tim Peters提供。)

The optparse Module

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: A Specialized Object Allocator

Pymalloc,一个由Vladimir Marangozov编写的专用对象分配器,是添加到Python 2.1的一个特性。Pymalloc旨在比系统malloc()更快,并且对于Python程序典型的分配模式具有更少的内存开销。分配器使用C的malloc()函数来获取大型内存池,然后满足来自这些池的较小内存请求。

在2.1和2.2中,pymalloc是一个实验性功能,默认情况下不启用;您必须通过向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系列。不能使用来自另一个系列的功能来操作分配有一个系列的内存。有一个族用于分配内存块,另一个族用于分配Python对象。

由于Tim Peters的许多工作,pymalloc在2.3还提供了调试功能,以捕获内存覆盖和双重释放在扩展模块和解释器本身。要启用此支持,请通过使用--with-pydebug运行configure来编译Python解释器的调试版本。

为了帮助扩展编写器,头文件Misc/pymemcompat.h随源代码一起发布到Python 2.3,允许Python扩展使用2.3接口来进行内存分配,同时从1.5开始编译任何版本的Python。 2。您将从Python的源代码分发中复制文件,并将其与扩展的源代码捆绑在一起。

也可以看看

https://hg.python.org/cpython/file/default/Objects/obmalloc.c
有关pymalloc实现的完整详细信息,请参阅Python源代码中文件Objects/obmalloc.c文件顶部的注释。上面的链接指向python.org SVN浏览器中的文件。

Build and C API Changes

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

  • 垃圾容器使用的循环检测实现已被证明是稳定的,因此现在已经被强制使用。如果没有它,您就无法再编译Python,并且已删除--with-cycle-gc切换到configure
  • 现在,通过在运行Python的configure脚本时提供--enable-shared,Python可以选择性地构建为共享库(libpython2.3.so(供稿:Ondrej Palkovsky。)
  • 现在已弃用DL_EXPORTDL_IMPORT宏。Python扩展模块的初始化函数现在应使用新宏PyMODINIT_FUNC声明,而Python核心通常使用PyAPI_FUNCPyAPI_DATA宏。
  • 通过向configure脚本提供--without-doc-strings可以对内建功能和模块编译没有任何docstrings的解释器。这使得Python可执行文件的大小减小了10%,但也意味着你无法获得Python内置函数的帮助。(供稿人:Gustavo Niemeyer。)
  • 现在不推荐使用PyArg_NoArgs()宏,并且应该更改使用它的代码。对于Python 2.2和更高版本,方法定义表可以指定METH_NOARGS标志,表示没有参数,然后可以删除参数检查。如果与Python前2.2版本的兼容性很重要,代码可以使用PyArg_ParseTuple(args, “”)比使用METH_NOARGS慢。
  • PyArg_ParseTuple() accepts new format characters for various sizes of unsigned integers: B for unsigned char, H for unsigned short int, I for unsigned int, and K for unsigned long long.
  • 添加了新功能PyObject_DelItemString(映射, char *键)作为 PyObject_DelItem(mapping, PyString_New(key))
  • 文件对象现在不同地管理它们的内部字符串缓冲区,在需要时按指数增加。这导致Lib/test/test_bufio.py中的基准测试大大加快(从57秒到1.7秒,根据一个测量)。
  • 现在可以通过在方法的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仿真层。The Python port for EMX tries to support all the POSIX-like capability exposed by the EMX runtime, and mostly succeeds; fork() and fcntl() are restricted by the limitations of the underlying emulation layer. 使用IBM的Visual Age编译器的标准OS / 2端口也获得了对区分大小写的导入语义的支持,作为将EMX端口集成到CVS中的一部分。(由Andrew MacIntyre提供)

在MacOS上,大多数工具箱模块都被弱连接以提高向后兼容性。这意味着如果当前操作系统版本中缺少单个例程,模块将不再失败。而调用缺少的例程将引发异常。(供稿人:Jack Jansen。)

在Python源代码分发的Misc/RPM/目录中找到的RPM规范文件已更新为2.3。(供稿人:Sean Reifschneider。)

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

Other Changes and Fixes

像往常一样,有一堆其他改进和错误修复分散在源码树。通过CVS更改日志进行搜索,发现应用了523个修补程序,并在Python 2.2和2.3之间修复了514个错误。这两个数字都可能是低估。

一些更显着的变化是:

  • If the PYTHONINSPECT environment variable is set, the Python interpreter will enter the interactive prompt after running a Python program, as if Python had been invoked with the -i option. 可以在运行Python解释器之前设置环境变量,或者可以由Python程序将其设置为其执行的一部分。

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

  • 用于构建文档的工具现在可以在Cygwin以及Unix下工作。

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

    除了在不使用-O的情况下运行Python时稍微加快速度时,很难检测到与Python代码产生的任何差异。

    访问帧对象的f_lineno字段的C扩展应调用PyCode_Addr2Line(f-> f_code, f-> f_lasti) t4 >这将有额外的效果,使代码在Python的早期版本的“python -O”下所需的工作。

    一个奇怪的新功能是跟踪功能现在可以分配给帧对象的f_lineno属性,更改下一个将执行的行。已利用此新功能将jump命令添加到pdb调试器。(由Richie Hindle执行)

Porting to Python 2.3

本部分列出了可能需要更改代码的上述更改:

  • yield现在总是一个关键字;如果它在代码中用作变量名,则必须选择不同的名称。

  • 对于字符串XYX in Y t2 >现在工作,如果X超过一个字符长。

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

  • 如果您具有包含8位字符的Unicode字符串,则必须通过在文件顶部添加注释来声明文件的编码(UTF-8,Latin-1或其他)。有关详细信息,请参见PEP 263: Source Code Encodings一节。

  • 通过_tkinter调用Tcl方法不再仅返回字符串。相反,如果Tcl返回其他对象,那么如果没有Python对等存在,那么这些对象将转换为等价的Python对象(如果存在)或使用_tkinter.Tcl_Obj对象包装。

  • 大的八进制和十六进制字面值如0xffffffff现在触发FutureWarning目前,它们存储为32位数字,并产生负值,但在Python 2.4中,它们将成为正的长整数。

    有几种方法来修复此警告。如果你真的需要一个正数,只需在字面值的末尾添加一个LIf you’re trying to get a 32-bit integer with low bits set and have previously used an expression such as ~(1 << 31), it’s probably clearest to start with all bits set and clear the desired upper bits. 例如,要仅清除顶部位(位31),可以写入0xffffffffL &amp;〜(1L

  • 您不能再通过分配__debug__来禁用断言。

  • 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

作者感谢以下人员为本文的各种草案提供建议,更正和协助: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 vonLö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。