What’s New In Python 3.0

作者:Guido van Rossum

本文解释了Python 3.0中与2.6相比的新功能。Python 3.0,也称为“Python 3000”或“Py3K”,是第一个有意向后不兼容的 Python版本。有比一个典型版本更多的更改,更多的是对所有Python用户很重要。然而,消化变化之后,你会发现Python真的没有改变这么多 - 总的来说,我们大多是修复知名的烦恼和疣,并删除了很多旧的。。

本文不试图提供所有新功能的完整规范,而是尝试提供方便的概述。有关详细信息,请参阅Python 3.0的文档和/或文本中引用的许多PEP。如果你想了解特定功能的完整实现和设计理由,PEP通常比常规文档具有更多的细节;但请注意,一旦功能已完全实施,PEP通常不会保持最新。

由于时间限制,本文档不像应该的那样完整。与新版本一样,源分发中的Misc/NEWS文件包含有关每个已更改的小事件的大量详细信息。

Common Stumbling Blocks

本节列出了那些最常见的变化,如果你习惯了Python 2.5。

Views And Iterators Instead Of Lists

一些知名的API不再返回列表:

  • dict方法dict.keys()dict.items()dict.values()例如,这不再工作:k = d.keys(); k.sort t4>使用k = sorted(d)(这在Python 2.5中也是一样有效)。

  • 此外,不再支持dict.iterkeys()dict.iteritems()dict.itervalues()方法。

  • map()filter()返回迭代器。如果你真的需要一个列表,并且输入序列都是相等的长度,一个快速的修复是将map()包含在list()list(map(...)),但更好的解决方案是使用列表推导式(尤其是当原始代码使用lambda时)所以它不需要一个列表。特别棘手的是调用函数的副作用的map()正确的转换是使用常规for循环(因为创建列表只是浪费)。

    如果输入序列不等长,则map()将在最短序列的终止时停止。为了与来自Python 2.x的map()完全兼容,还应将itertools.zip_longest()map(func, *sequences) becomes list(map(func, itertools.zip_longest(*sequences))).

  • range()现在表现得像xrange()用于表现,除了它可以使用任意大小的值。后者不再存在。

  • zip()现在返回一个迭代器。

Ordering Comparisons

Python 3.0简化了排序比较的规则:

  • The ordering comparison operators (<, <=, >=, >) raise a TypeError exception when the operands don’t have a meaningful natural ordering. Thus, expressions like 1 < '', 0 > None or len <= len are no longer valid, and e.g. 引发TypeError而不是返回False推论是,排序异质列表不再有意义 - 所有元素必须相互比较。注意,这不适用于==!=运算符:不同不可比类型的对象总是比较不相等的对象。
  • builtin.sorted()list.sort()不再接受提供比较函数的cmp参数。请改用参数。N.B.反向参数现在是“仅限关键字”。
  • cmp()函数应被视为已完成,并且不再支持__cmp__()特殊方法。使用__lt__()用于排序,__eq__()__hash__()以及其他需要的丰富比较。(If you really need the cmp() functionality, you could use the expression (a > b) - (a < b) as the equivalent for cmp(a, b).)

Integers

  • PEP 237:本质上,long已重命名为int也就是说,只有一个内建整数类型,命名为int;但它的行为主要类似于旧的long类型。
  • PEP 238:像1/2的表达式返回浮点值。使用1//2获取截断行为。(后一种语法已经存在多年,至少从Python 2.2开始)。
  • 已删除sys.maxint常量,因为整数值不再有限制。但是,sys.maxsize可以用作大于任何实际列表或字符串索引的整数。它符合实现的“自然”整数大小,并且通常与在同一平台上的先前版本中的sys.maxint相同(假设相同的构建选项)。
  • 长整型的repr()不再包括结尾的L,因此无条件地删除该字符的代码将会取代最后一个数字。(改为使用str())。
  • 八进制字面值不再是0720的形式;请改用0o720

Text Vs. Data Instead Of Unicode Vs. 8-bit

你认为你知道的二进制数据和Unicode的一切都改变了。

  • Python 3.0使用text和(binary)数据的概念,而不是Unicode字符串和8位字符串。所有文本都是Unicode;但编码 Unicode表示为二进制数据。用于保存文本的类型为str,用于保存数据的类型为bytes与2.x情况的最大的区别是,任何尝试混合文本和数据在Python 3.0引发TypeError,而如果你混合Unicode和8位字符串在Python 2.x,它如果8位字符串只包含7位(ASCII)字节,则会工作,但如果它包含非ASCII值,则会得到UnicodeDecodeError这种价值特定的行为多年来造成了许多悲伤的脸。
  • 作为哲学的这种变化的结果,几乎所有使用Unicode,编码或二进制数据的代码很可能必须改变。变化是更好的,因为在2.x世界有许多错误与混合编码和未编码的文本。要在Python 2.x中准备,请对所有未编码的文本使用unicode,对于二进制或编码数据,请使用str然后,2to3工具将为您完成大部分工作。
  • 对于Unicode文本,您不能再使用u"..."字面值。但是,对于二进制数据,必须使用b"..."字面值。
  • 由于strbytes类型不能混合,因此必须始终在它们之间进行显式转换。Use str.encode() to go from str to bytes, and bytes.decode() to go from bytes to str. 您还可以使用字节(s, encoding = ...)str(b, encoding = ...)
  • strbytes类型是不可变的。有一个单独的可变类型来保存缓冲的二进制数据,bytearray几乎所有接受bytes的API也接受bytearray可变API基于collections.MutableSequence
  • 原始字符串字面值中的所有反斜杠都按字面解释。这意味着不会对原始字符串中的'\U''\u'转义进行特殊处理。例如,r'\u20ac'是Python 3.0中的6个字符的字符串,而在2.6中,ur'\u20ac'(当然,这种改变只影响原始字符串字面值;在Python 3.0中,欧元字符是'\u20ac')。
  • 内建basestring抽象类型已删除。请改用strstrbytes类型没有足够的共同功能保证共享基类。2to3工具(见下文)用str替换每次出现的basestring
  • 作为文本文件打开的文件(仍为open()的默认模式)始终使用编码在内存中的字符串和磁盘上的字节之间进行映射。二进制文件(在模式参数中以b打开)始终使用内存中的字节。这意味着如果使用不正确的模式或编码打开文件,I / O可能会大声失败,而不是默默地生成不正确的数据。这也意味着,甚至Unix用户将不得不在打开文件时指定正确的模式(文本或二进制)。有一个平台相关的默认编码,在Unixy平台上可以使用LANG环境变量(有时还与一些其他平台相关的环境变量)设置。在许多情况下,但不是全部,系统默认为UTF-8;您不应该依赖此默认值。任何读取或写入超过纯ASCII文本的应用程序应该可以覆盖编码。不再需要在codecs模块中使用编码感知流。
  • sys.stdinsys.stdoutsys.stderr的初始值现在是仅Unicode文本文件(即,它们是io.TextIOBase)。要使用这些流读取和写入字节数据,您需要使用其io.TextIOBase.buffer属性。
  • 文件名作为(Unicode)字符串传递到API并从API返回。这可能会出现平台特定的问题,因为在某些平台上,文件名是任意字节字符串。(另一方面,在Windows文件名本地存储为Unicode。)作为一种解决方法,大多数API(例如open()os模块中的许多函数)使文件名接受bytes对象以及字符串,要求一个bytes返回值。因此,如果参数是bytes实例,os.listdir()则返回bytes实例的列表,os.getcwdb()bytes实例返回当前工作目录。请注意,当os.listdir()返回字符串列表时,会省略无法正确解码的文件名,而不是提高UnicodeError
  • 某些系统API(如os.environsys.argv)也会在系统提供的字节无法使用默认编码解释时出现问题。设置LANG变量​​并重新运行程序可能是最好的方法。
  • PEP 3138:字符串的repr()不再转义非ASCII字符。然而,它仍然在Unicode标准中转义具有不可打印状态的控制字符和代码点。
  • PEP 3120:默认源编码现在是UTF-8。
  • PEP 3131:标识符中现在允许使用非ASCII字母。(但是,标准库保留ASCII,只有注释中的贡献者名称除外。)
  • StringIOcStringIO模块消失了。请改为导入io模块,并分别对文本和数据使用io.StringIOio.BytesIO
  • 另请参阅为Python 3.0更新的Unicode HOWTO

Overview Of Syntax Changes

本节简要介绍Python 3.0中每个句法的变化。

New Syntax

  • PEP 3107:函数参数和返回值注释。这提供了标注函数的参数和返回值的标准化方式。除了它们可以在运行时使用__annotations__属性进行内省,没有附加到这样的注解的语义。目的是鼓励通过元类,装饰器或框架进行实验。

  • PEP 3102:仅限关键字的参数。在参数列表*args之后发生的命名参数必须使用关键字语法在调用中指定。您还可以在参数列表中使用裸的*来指示您不接受可变长度的参数列表,但您确实具有仅关键字的参数。

  • 在类定义中的基类的列表之后允许关键字参数。这被用于指定元类的新约定使用(见下一节),但也可以用于其他目的,只要元类支持它。

  • PEP 3104nonlocal语句。使用非本地 x,您现在可以直接分配给外部(但非全局)作用域中的变量。nonlocal是一个新的保留字。

  • PEP 3132:Extended Iterable分拆。你现在可以写a, b, * rest = some_sequence 甚至* rest, a = stuffrest对象总是一个(可能为空)列表;右侧可以是任何可迭代的。例:

    (a, *rest, b) = range(5)
    

    这将a设置为0b4,并将rest设置为 [1, 2, 3]

  • 字典推导式:{k: v for k, v in stuff}表示与dict(stuff)相同,但更灵活。(这是 PEP 274:-)

  • 设置字面值,例如。{1, 2}注意,{}是一个空字典;对于空集,使用set()也支持设置推导式;例如{x for x in stuff} t0 >意味着与set(stuff)相同的东西,但是更灵活。

  • 新八度字面值0o720(已在2.6中)。旧八进制字面值(0720)不见了。

  • 新二进制字面值。0b1010(已经在2.6中),并且有一个新的相应内建函数bin()

  • 字节字面值用前导bB引入,并且有一个新的对应内建函数bytes()

Changed Syntax

  • PEP 3109 and PEP 3134: new raise statement syntax: raise [expr [from expr]]. 见下文。

  • aswith现在是保留字。(实际上从2.6开始)。

  • TrueFalseNone是保留字。(2.6已部分强制实施None的限制。)

  • Change from except exc, var to except exc as var. 请参阅 PEP 3110

  • PEP 3115:新的元类语法。代替:

    class C:
        __metaclass__ = M
        ...
    

    您现在必须使用:

    class C(metaclass=M):
        ...
    

    不再支持模块全局__metaclass__变量​​。(这是一个拐杖,使它更容易默认为新式类,而不从object导出每个类。)

  • List comprehensions no longer support the syntactic form [... for var in item1, item2, ...]. Use [... for var in (item1, item2, ...)] instead. 还要注意,列表推导式具有不同的语义:它们更接近于list()构造函数中的生成器表达式的语法糖,特别是循环控制变量不再泄漏到周围范围。

  • 省略号...)可以用作任何地方的原子表达式。(以前它只允许在切片。)此外,必须现在拼写为...。 (以前,它也可以拼写为 ,只是偶然的语法。

Removed Syntax

  • PEP 3113:删除了Tuple参数拆分。您不能再写def foo(a, (b, c)): ...。使用def foo(a, b_c): b, c = b_c
  • 删除反引号(改用repr())。
  • 已移除<>(改用!=)。
  • 已移除关键字:exec()不再是关键字;它仍然是一个功能。(幸运的是,函数语法也在2.x.中接受)还要注意,exec()不再需要一个流参数;而不是exec(f),您可以使用exec(f.read())
  • 整数字面值不再支持结尾lL
  • 字符串字面值不再支持前导uU
  • 仅允许在模块级别的from 模块 import *语法,
  • The only acceptable syntax for relative imports is from .[module] import name. 所有import表单不是以.被解释为绝对进口。 PEP 328
  • 经典类已经走了。

Changes Already Present In Python 2.6

由于许多用户可能会从Python 2.5直接跳转到Python 3.0,本节提醒读者最初为Python 3.0设计的新功能,但是已经返回到Python 2.6。对于更长的描述,应参考What’s New in Python 2.6中的相应部分。

Library Changes

由于时间限制,本文档并不详尽地涵盖标准库的非常广泛的更改。 PEP 3108是库的主要更改的参考。这里是一个胶囊审查:

  • 许多旧模块被删除。Some, like gopherlib (no longer used) and md5 (replaced by hashlib), were already deprecated by PEP 4. 由于去除了对诸如Irix,BeOS和Mac OS 9的各种平台(参见 PEP 11)的支持,其他的被删除。由于缺少使用或者因为存在更好的替换,一些模块也被选择在Python 3.0中删除。有关详细列表,请参见 PEP 3108

  • bsddb3包已删除,因为它在核心标准库中的存在已证明随着时间的推移,由于测试不稳定性和Berkeley DB的发布计划,是核心开发人员的特殊负担。但是,该软件包仍然有效,外部维护在https://www.jcea.es/programacion/pybsddb.htm

  • 某些模块已重命名,因为他们的旧名称不符合 PEP 8或其他原因。下面是列表:

    旧名称新名称
    _winregwinreg
    ConfigParserconfigparser
    copy_reg复制
    队列队列
    SocketServersocketserver
    标记库_markupbase
    reprreprlib
    test.test_supporttest.support
  • Python 2.x中的一个常见模式是在纯Python中实现一个版本的模块,将可选加速版本实现为C扩展;例如picklecPickle这会导入导入加速版本的负担,并且退回到这些模块的每个用户的纯Python版本。在Python 3.0中,加速版本被认为是纯Python版本的实现细节。用户应该总是导入标准版本,尝试导入加速版本并回退到纯Python版本。pickle / cPickle对接受这种治疗。profile模块位于3.1的列表中。StringIO模块已在io模块中转换为类。

  • 一些相关的模块已经被分组成包,通常子模块名称已经被简化。生成的新包是:

    • dbm (anydbm, dbhash, dbm, dumbdbm, gdbm, whichdb).
    • htmlHTMLParserhtmlentitydefs)。
    • http (httplib, BaseHTTPServer, CGIHTTPServer, SimpleHTTPServer, Cookie, cookielib).
    • tkinter(除turtle之外的所有Tkinter相关模块)。turtle实际上并不关心tkinter还要注意,从Python 2.6开始,turtle的功能已经大大增强了。
    • urlliburlliburllib2urlparserobotparse)。
    • xmlrpcxmlrpclibDocXMLRPCServerSimpleXMLRPCServer)。

PEP 3108未涵盖的对标准库模块的一些其他更改:

  • 已杀死sets使用内建set()类。
  • 清除sys模块:remove sys.exitfunc()sys.exc_clear()sys.exc_typesys.exc_valuesys.exc_traceback(请注意sys.last_type等。保留)。
  • 清除array.array类型:read()write()请改用fromfile()tofile()此外,数组的'c'类型代码没有了 - 对于字符使用'b',对于Unicode字符使用'u'
  • 清除operator模块:删除sequenceIncludes()isCallable()
  • 清除thread模块:acquire_lock()release_lock()已消失;请改用acquire()release()
  • 清除random模块:删除jumpahead() API。
  • new模块已删除。
  • The functions os.tmpnam(), os.tempnam() and os.tmpfile() have been removed in favor of the tempfile module.
  • tokenize模块已更改为使用字节。主入口点现在为tokenize.tokenize(),而不是generate_tokens。
  • string.letters和其朋友(string.lowercasestring.uppercase)都消失了。使用string.ascii_letters等。代替。(删除的原因是string.letters和朋友有locale特定的行为,这是一个糟糕的想法,这种吸引人地命名的全局“常量”。)
  • 将模块__builtin__重命名为builtins(删除下划线,添加“s”)。在大多数全局命名空间中找到的__builtins__变量​​不变。要修改内置函数,您应该使用builtins而不是__builtins__

PEP 3101: A New Approach To String Formatting

  • 内建字符串格式化操作的新系统替换了%字符串格式化操作符。(但是,%操作符号仍然受支持;它将在Python 3.1中弃用,并在稍后从语言中移除)。阅读 PEP 3101以获取完整的勺子。

Changes To Exceptions

用于提升和捕获异常的API已清除,​​并添加了新的强大功能:

  • PEP 352:所有异常必须从BaseException派生(直接或间接)。这是异常层次结构的根。这不是新建议,但要继承BaseException需求 t>是新的。(Python 2.6仍然允许引发经典类,并且对可以捕获的内容没有限制。)因此,字符串异常终于真正完全死了。

  • 几乎所有的异常都应该从Exception派生; BaseException应仅用作应该仅在顶层处理的异常的基类,例如SystemExitKeyboardInterrupt处理除后一类别之外的所有异常的推荐习语是使用除 Exception之外的except

  • StandardError已移除。

  • 异常不再表现为序列。请改用args属性。

  • PEP 3109:提高异常。您现在必须使用提高 Exception args > raise Exception args此外,您不能再显式指定追溯;相反,如果您这样做,您可以直接分配到__traceback__属性(见下文)。

  • PEP 3110:捕获异常。您现在必须使用,除了 SomeException variable,而不是 except SomeException variable此外,当except块之后,变量​​被显式删除。

  • PEP 3134:异常链接。有两种情况:隐式链接和显式链接。exceptfinally处理程序块中引发异常时,将发生隐式链接。这通常发生由于处理程序块中的错误;我们称之为次要异常。在这种情况下,原始异常(正在处理)保存为辅助异常的__context__属性。使用以下语法调用显式链接:

    raise SecondaryException() from primary_exception
    

    (其中primary_exception是产生异常对象的任何表达式,可能是先前捕获的异常)。在这种情况下,主异常存储在辅助异常的__cause__属性上。当发生未处理的异常时,打印的跟踪链将导致__cause____context__属性,并为链的每个组件打印单独的追溯,主要异常在顶部。(Java用户可能会识别此行为。)

  • PEP 3134:异常对象现在将其回溯存储为__traceback__属性。这意味着异常对象现在包含所有与异常有关的信息,并且使用sys.exc_info()的理由较少(虽然后者不会被删除)。

  • 当Windows无法加载扩展模块时,会改进一些异常消息。例如,错误 代码 193现在是%1 不是 a 有效 Win32 字符串现在处理非英语语言环境。

Miscellaneous Other Changes

Operators And Special Methods

  • != now returns the opposite of ==, unless == returns NotImplemented.
  • “未绑定方法”的概念已从语言中删除。当将方法引用为类属性时,现在可以得到一个简单的函数对象。
  • __getslice__()__setslice__()__delslice__()被杀死。语法a[i:j]现在转换为a .__ getitem __(slice(i, j)) (或__setitem__()__delitem__()时,分别用作指定或删除目标)。
  • PEP 3114:标准next()方法已重命名为__next__()
  • The __oct__() and __hex__() special methods are removed – oct() and hex() use __index__() now to convert the argument to an integer.
  • 已移除对__members____methods__的支持。
  • 名为func_X的函数属性已重命名为使用__X__形式,在函数属性命名空间中释放用户定义属性的这些名称。To wit, func_closure, func_code, func_defaults, func_dict, func_doc, func_globals, func_name were renamed to __closure__, __code__, __defaults__, __dict__, __doc__, __globals__, __name__, respectively.
  • __nonzero__()现在是__bool__()

Builtins

  • PEP 3135:新super()现在可以调用super()而不带参数(假设这是在class语句中定义的常规实例方法),将自动选择正确的类和实例。使用参数,super()的行为不变。
  • PEP 3111raw_input()已重命名为input()也就是说,新的input()函数从sys.stdin读取一行,并返回带有拖尾的换行符。如果输入过早终止,则引发EOFError要获得input()的旧行为,请使用eval(input())
  • 添加了新的内建函数next()以调用对象上的__next__()方法。
  • round()函数舍入策略和返回类型已更改。精确中途情况现在四舍五入到最接近的偶数结果,而不是远离零。(例如,round(2.5)现在返回2,而不是3。)round(x [, n])现在委托给x.__round__([n])返回浮点。当使用两个参数调用时,通常在使用单个参数和类型与x相同的值时调用时返回一个整数。
  • 已将intern()移动到sys.intern()
  • 删除:apply()而不是应用(f, args)使用f(*args)
  • 已移除callable()您可以使用isinstance(f, 容器.Callable)代替callable(f)operator.isCallable()函数也没有了。
  • 已移除coerce()这个函数不再服务于一个目的,现在经典类已经走了。
  • 已移除execfile()而不是execfile(fn)使用exec(open(fn).read())
  • 删除了file类型。使用open()现在有几种不同类型的流可以在io模块中返回。
  • 已移除reduce()如果你真的需要它,使用functools.reduce();然而,99%的显式for循环的可读性更强。
  • 已移除reload()使用imp.reload()
  • 已移除。dict.has_key() - 使用in操作符号。

Build and C API Changes

由于时间限制,这里有一个非常的C API更改列表。

  • 支持多个平台被删除,包括但不限于Mac OS 9,BeOS,RISCOS,Irix和Tru64。
  • PEP 3118:新的缓冲区API。
  • PEP 3121:扩展模块初始化和完成。
  • PEP 3123:使PyObject_HEAD符合标准C.
  • 没有更多的C API支持限制执行。
  • PyNumber_Coerce()PyNumber_CoerceEx()PyMember_Get()PyMember_Set()
  • 新C API PyImport_ImportModuleNoBlock(),工作方式类似于PyImport_ImportModule(),但不会在导入锁定时阻塞(返回错误)。
  • 重命名布尔转换C级槽和方法:nb_nonzero现在为nb_bool
  • 已从C API中移除METH_OLDARGSWITH_CYCLE_GC

Performance

3.0概括的最终结果是Python 3.0运行的pystone基准比Python 2.5慢大约10%。最可能的最大的原因是为小整数移除特殊外壳。有改进的余地,但它会发生后3.0发布!

Porting To Python 3.0

对于将现有的Python 2.5或2.6源代码移植到Python 3.0,最好的策略如下:

  1. (先决条件:)从优秀的测试覆盖开始。
  2. 端口到Python 2.6。这应该比从Python 2.x到Python 2(x + 1)的平均端口没有更多的工作。确保所有测试通过。
  3. (仍然使用2.6 :)打开-3命令行开关。这将启用在3.0中将删除(或更改)的功能的警告。再次运行测试套件,并修复您收到警告的代码,直到没有留下警告,并且所有测试仍然通过。
  4. 在源代码树上运行2to3源到源翻译器。(有关此工具的更多信息,请参阅2to3 - Automated Python 2 to 3 code translation。)在Python 3.0下运行翻译的结果。手动修复任何剩余的问题,修复问题,直到所有测试再次通过。

不建议尝试编写在Python 2.6和3.0下都保持不变的源代码;你必须使用非常扭曲的编码风格,例如。避免print语句,元类等。如果您维护一个需要支持Python 2.6和Python 3.0的库,最好的方法是通过编辑2.6版本的源代码并再次运行2to3转换器来修改上述步骤3,而不是比编辑3.0版本的源代码。

要将C扩展模块移植到Python 3.0,请参阅Porting Extension Modules to Python 3