Python 3.0 有什么新变化¶
- 作者:
Guido van Rossum
本文介绍 Python 3.0 与 2.6 相比的新特性。 Python 3.0 也被称为 "Python 3000" 或 "Py3K",是有史以来第一个 有意向下不兼容 的 Python 版本。 Python 3.0 于 2008 年 12 月 3 日发布。 与一般的发布版本相比,Python 3.0 有更多的变化,而且对所有 Python 用户都很重要。 不过,在理解了这些改动之后,您会发现 Python 其实并没有太大的变化 -- 总的来说,我们主要是修复了一些众所周知的问题和缺陷,并删除了许多旧的垃圾。
本文并不试图提供所有新特性的完整规范,而是试图提供一个方便的概述。 要了解完整的细节,您应该参考 Python 3.0 的文档和/或文中引用的许多 PEP。 如果您想了解某个特性的完整实现和设计原理,PEP 通常比常规文档有更多的细节;但要注意的是,一旦某个特性被完全实现,PEP 通常不会保持更新。
由于时间有限,本文档不够完整。 对于新发布的版本,源代码发行版中的 Misc/NEWS 文件总是包含大量关于每一个细小改动的详细信息。
常见的绊脚石¶
本节列出了在你已习惯了 Python 2.5 的情况下最有可能让您感到困惑的几处更改。
Print 是函数¶
print 语句已被 print() 函数取代,其关键字参数取代了旧 print 语句 (PEP 3105) 的大部分特殊语法。 示例:
旧: print "The answer is", 2*2
新: print("The answer is", 2*2)
旧: print x, # 末尾逗号将抑制换行符
新: print(x, end=" ") # 添加一个空格代替换行符
旧: print # 打印一个换行符
新: print() # 你必须调用函数!
旧: print >>sys.stderr, "fatal error"
新: print("fatal error", file=sys.stderr)
旧: print (x, y) # 打印 repr((x, y))
新: print((x, y)) # 不同于 print(x, y)!
你还可以自定义条目间的分隔符,例如
print("There are <", 2**32, "> possibilities!", sep="")
这将产生如下结果:
There are <4294967296> possibilities!
注意
用视图和迭代器取代列表¶
某些知名的 API 将不再返回列表:
dict方法dict.keys()、dict.items()和dict.values()返回 “视图” 而不是列表。 例如,这个写法不再有效:k = d.keys(); k.sort()。 请使用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)变成list(map(func, itertools.zip_longest(*sequences)))。现在
range()的行为与过去xrange()的行为类似,区别在于它能处理任意大小的值。 后者已不复存在。zip()现在将返回一个迭代器。
排序比较¶
Python 3.0 简化了排序比较的规则:
当操作数不存在有意义的自然排序时,排序比较操作符 (
<,<=,>=,>) 会引发 TypeError 异常。 因此,像1 < '',0 > None或len <= len这样的表达式不再有效,例如None < None会引发TypeError而不是返回False。 由此推论,对异构列表进行排序不再有意义 —— 所有元素必须相互可比。 请注意,这不适用于==和!=操作符:不同的不可比类型的对象总是互不相等的。sorted()和list.sort()不再接受提供比较函数的 cmp 参数。 请改用 key 参数。 注意 key 和 reverse 参数现在都是“仅限关键字”参数。cmp()函数应视为已不复存在,而__cmp__()特殊方法再不再受支持。 请使用__lt__()进行排序,并根据需要使用__eq__()与__hash__(),以及其他富比较操作。 (如果你确实需要cmp()的功能,你可以使用表达式(a > b) - (a < b)作为cmp(a, b)的等价形式。)
整数¶
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的形式。
文本与数据而不是 Unicode 与 8 比特位¶
你对二进制数据和 Unicode 的所有认知都已改变。
Python 3.0 使用 文本 和 (二进制) 数据 等概念来替代 Unicode 字符串和 8 位字符串。 所有文本均使用 Unicode;不过 已编码 Unicode 是以二进制数据来表示的。 用于存放文本的类型是
str,用于存放数据的类型是bytes。 与 2.x 场景的最大区别是在 Python 3.0 中任何混用文本和数据的尝试都将引发TypeError,而当你在 Python 2.x 中混用 Unicode 和 8 位字符串时,如果 8 位字符串恰好仅包含 7 位 (ASCII) 字节数据那就没有问题,但是如果包含非 ASCII 值则将引发UnicodeDecodeError。 这种依赖于特定值的行为多年来造成了无数的苦恼。作为此项设计哲学方面的修改造成的影响,几乎所有使用 Unicode、编码格式或二进制数据的代码都很有可能必须被修改。 这项改变是有益的,因为在 2.x 世界中存在着无数涉及混用已编码和未编码文本的程序缺陷。 要在 Python 2.x 中做好准备,请使用
unicode表示所有未编码文本,只对二进制或已编码数据使用str。 这样2to3工具将为你完成大部分工作。你不能再使用
u"..."字面值来表示 Unicode 文本。 不过,你必须使用b"..."字面值来表示二进制数据。由于
str和bytes类型无法混用,你必须始终在它们之间执行显式转换。 使用str.encode()将str转为bytes,并使用bytes.decode()将bytes转为str。 你也可以分别使用bytes(s, encoding=...)和str(b, encoding=...)。与
str一样,bytes类型是不可变的。 还有一个单独的 可变 类型用于保存带缓冲的二进制数据,即bytearray。 几乎所有接受bytes的 API 也都接受bytearray。 这个可变 API 是基于collections.MutableSequence。原始字符串字面中的所有反斜线均按字面解释。 这意味着原始字符串中的
'\U'和'\u'转义符不会被特殊处理。 例如,在 Python 3.0 中,r'\u20ac'是一个包含 6 个字符的字符串,而在 2.6 中,ur'\u20ac'是一个 “欧元” 字符。 (当然,这种变化只影响原始字符串的字面意义;在 Python 3.0 中,欧元字符是'\u20ac'。)内置的
basestring抽象类型已被移除。 请改用str。str和bytes类型在功能上没有足够的共通性因此不需要有共享的基类。2to3工具(见下文)会将所有basestring都替换为str。作为文本文件打开的文件(仍然是
open()的默认模式)总是会使用一个编码格式在(内存中的)字符串和(磁盘中的)字节串之间建立映射。 二进制文件(将 mode 参数设为b来打开)在内存中总是会使用数字串。 这意味着如果一个文件是使用不正确的模式或编码格式打开的,I/O 操作很可能会报告失败,而不是静默地产生不正确的数据。 这也意味着即使是 Unix 用户在打开文件时也必须指定正确的模式(文本或二进制)。 存在一个依赖于具体平台的默认编码格式,在类 Unix 平台上可以通过LANG环境变量来设置(有时也会使用其他一些平台专属的语言区域相关的环境变量)。 在多数情况下,系统默认使用 UTF-8,但并非全都如此;你绝不应该依赖这个默认值。 任何读写超出纯 ASCII 文本范围的内容的应用程序都应该提供重写编码格式的选项。 现在已不再需要使用codecs模块中可感知编码格式的流。sys.stdin、sys.stdout和sys.stderr的初始值现在是仅 Unicode 的文本文件(即它们是io.TextIOBase的实例)。 要使用这些数据流读写字节数据,需要使用它们的io.TextIOBase.buffer属性。文件名是以(Unicode)字符串的形式传给 API 并返回的。 这可能产生特定平台专属的问题因为在某些平台上文件名强制使用字节串。 (另一方面,在 Windows 上文件名则原生存储为 Unicode。) 为绕过此问题,多数接受文件名的 API(例如
open()和os模块中的许多函数)都同时接受bytes对象和字符串,而少数 API 会发出要求bytes返回值的提示。 因而,当参数为bytes的实例时os.listdir()会返回由bytes实例组成的列表,os.getcwdb()则会将当前工作目录作为bytes实例返回。 请注意当os.listdir()返回字符串的列表时,无法被正确解码的文件名会被忽略而不是引发UnicodeError。当系统提供的字节无法使用默认编码进行解释时,一些系统 API,如
os.environ和sys.argv,也会出现问题。 最好的办法可能是设置LANG变量并重新运行程序。PEP 3138: 字符串的
repr()将不再转义非 ASCII 字符。 不过,它仍然会转义控制字符和在 Unicode 标准中具有不可打印状态的码位。PEP 3120:现在默认的源码编码格式是UTF-8。
PEP 3131: 现在允许在标识符中使用非 ASCII 字符(不过,标准库中的异常和注释中的贡献者名字仍然只使用 ASCII 字符)。
StringIO和cStringIO模块已被去除。 作为替代,请导入io模块并分别为文本和数据使用io.StringIO或io.BytesIO。另请参阅 Unicode 指南,其内容已针对 Python 3.0 进行更新。
语法变化概述¶
本节提供了 Python 3.0 中每个 语法 变化的简要说明。
新语法¶
PEP 3107: 函数参数和返回值标注。 这提供了一种标注函数形参和返回值的标准方式。 并没有与这种标注相关联的特殊语法而只是可以使用
__annotations__属性在运行时对它们进行内省。 其目的是鼓励在元类、装饰器和框架中尝试应用标注。PEP 3102:仅限关键字参数。在参数列表``*args`` 之后出现的命名参数 必须 在调用中使用关键字语法指定。也可以在参数列表中使用``*``来表示不接受长度可变的参数列表,但可以使用只包含关键字的参数。
类定义中的基类列表后允许使用关键字参数。 这是用于指定元类的新约定(见下一节),但也可用于其他目的,只要元类支持它。
PEP 3104:
nonlocal语句。 现在你可以使用nonlocal x来允许直接赋值到一个外层(但非全局)作用域。nonlocal是新的保留字。PEP 3132: 扩展可迭代对象解包。 你现在可以编写像
a, b, *rest = some_sequence这样的代码。 甚至*rest, a = stuff。rest对象将总是为一个(可能为空的)列表;右侧的对象可以是任意可迭代对象。 例如:(a, *rest, b) = range(5)
这会将 a 设为
0,b 设为4,而将 rest 设为[1, 2, 3]。新增字典推导式:
{k: v for k, v in stuff}的含义与dict(stuff)相同但是更为灵活。 (对此特性的解释见 PEP 274。 :-)新增集合字面值,例如
{1, 2}。 请注意{}是空字典;要用set()表示空集合。 集合推导式也受到支持;例如{x for x in stuff}的含义与set(stuff)相同但是更为灵活。新增八进制字面值,例如
0o720(已存在于 2.6 中)。 旧的八进制字面值 (0720) 已不复存在。新增二进制字面值,例如
0b1010(已存在于 2.6 中),还有对应的新增内置函数bin()。引入了带有
b或B前缀的字节串字面值,还有对应的新增内置函数bytes()。
语法变化¶
PEP 3109 和 PEP 3134: 新增
raise语句的语法:raise [expr [from expr]]。 见下文。现在
as和with是保留关键字。 (实际是从 2.6 开始。)True,False和None已成为保留关键字。 (2.6 已经对None部分强制应用限制。)PEP 3115: 新的元类语法。 替换:
class C: __metaclass__ = M ...
你现在需要使用:
class C(metaclass=M): ...
模块级全局变量
__metaclass__已不再受支持。 (它是一个令默认使用新式类而无需从object派生每一个类的辅助工具。)列表推导式不再支持
[... for var in item1, item2, ...]这样的语法形式。 请改用[... for var in (item1, item2, ...)]。 还要注意列表推导式具有不同的句法:它们更像是list()构造器内部用于生成器表达式的语法糖,具体来说就是循环控制变量将不会再泄漏到外层作用域中。ellipsis (
...) 可以在任何地方作为原子表达式使用。(以前只允许在片段中使用。)另外,现在 必须 拼写为``...`` 。(以前也可以拼写为``. . .`` ,这只是一个偶然的语法。)
移除的语法¶
PEP 3113: 元组形参解包已被移除。 你不能再使用
def foo(a, (b, c)): ...的写法。 请改用def foo(a, b_c): b, c = b_c。移除了反引号 (请改用
repr())。移除了
<>(请改用!=)。移除的关键字:
exec()不再是一个关键字;它仍是一个函数。 (幸运的是该函数语法也在 2.x 中被接受。) 还要注意exec()将不再接受流作为参数;你可以将原来的exec(f)改为使用exec(f.read())。整数字面值不再支持
l或L后缀。字符串字面值不再支持
u或U前缀。唯一可接受的相对导入语法为
from .[module] import name。 所有不以.开头的import形式都将被解读为绝对导入。 (PEP 328)经典类已不复存在。
已存在于 Python 2.6 中的改变¶
由于许多用户可能会直接从 Python 2.5 跳到 Python 3.0,因此本节提醒读者注意最初为 Python 3.0 设计但后来移植到 Python 2.6 的新特性。 如需更详细的说明请参阅 Python 2.6 有什么新变化 中的相应章节。
PEP 343: "with" 语句。 现在
with语句已是一个标准特性而不再需要从__future__导入。 另请参阅 编写上下文管理器 和 contextlib 模块。PEP 366: 从主模块显式相对导入。 这增强了
-m选项在被引用的模块位于包中时的实用性。PEP 3101: 高级字符串格式。 注意:2.6 说明文档提到
format()方法同时适用于 8 位和 Unicode 字符串。 在 3.0 中,只有str类型(带有 Unicode 支持的文本字符串)才支持此方法;bytes类型并不支持。 最终的计划是使其成为仅针对字符串格式化的 API,并在 Python 3.1 中开始弃用%字符串运算符。PEP 3105: print 改为函数。 现在这已是一个标准特性而不再需要从
__future__导入。 更多详情见上文。PEP 3110: 异常处理的变更。 现在
exceptexcasvar 语法已成为标准而exceptexc, var 不再受到支持。 (当然,asvar 部分仍为可选项。)PEP 3112: 字节字面值。 现在
b"..."字节串字面值标记法(及其变化形式如b'...',b"""..."""和br"..."等将产生bytes类型的字面值。PEP 3116: 新 I/O 库。
io模块现在是执行文件 I/O 的标准方式。 内置的open()函数现在是io.open()的别名并增加了额外的关键字参数 encoding, errors, newline 和 closefd。 还请注意无效的 mode 参数现在会引发ValueError,而不是IOError。 在文本文件对象之下的二进制文件对象可作为f.buffer来访问(但要记住文本对象会为自己保留一个缓冲区以加快编码和解码操作的速度)。PEP 3118: 修改缓冲区协议。 旧的内置
buffer()现已完全不复存在;新的内置memoryview()提供了(基本)类似的功能。PEP 3119: 抽象基类。 现在
abc模块以及在collections模块中定义的 ABC 在本语言中扮演了更为重要的角色,而内置的多项集类型如dict和list分别与collections.MutableMapping和collections.MutableSequenceABC 保持对应。PEP 3127: 整型文字支持和语法。 如上文所述,新的八进制字面值标记法是唯一受支持的形式,并增加了二进制字面值。
PEP 3141: 数字的类型层级结构。
numbers模块是 ABC 的另一个新用例,它定义了 Python 的“数字层级塔”。 另请注意新的fractions模块,它实现了numbers.Rational。
库的修改¶
由于时间有限,本文档并未完全覆盖标准库的所有变化内容。 PEP 3108 引用了对标准库的主要修改。 以下是精简版的预览:
许多旧模块已被移除。 其中一些,如
gopherlib(不再有用) 和md5(被hashlib替代),已根据 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,或是出于各种其他理由。 具体列表如下:
旧名称
新名称
_winreg
winreg
ConfigParser
configparser
copy_reg
copyreg
Queue
queue
SocketServer
socketserver
markupbase
_markupbase
repr
reprlib
test.test_support
test.support
在 Python 2.x 中的常见模式是某个模块有一个以纯 Python 实现的版本,并有一个作为 C 扩展实现的加速版本;例如,
pickle和cPickle。 这造成每个此类模块的用户存在导入加速版本并在必要时回退到纯 Python 版本的负担。 在 Python 3.0 中,加速版本将被视为纯 Python 版本的实现细节。 用户应当总是导入标准版本,该版本会尝试导入加速版本并在必要时回退到纯 Python 版本。pickle/cPickle对就获得了这样的处置。profile模块被加入了 3.1 版的处置计划。StringIO模块已被转为io模块中的一个类。一些有关联的模块已被组织为包,通常其子模块名也得到了简化。 这样产生的新包有:
dbm(anydbm,dbhash,dbm,dumbdbm,gdbm,whichdb)。html(HTMLParser,htmlentitydefs)。http(httplib,BaseHTTPServer,CGIHTTPServer,SimpleHTTPServer,Cookie,cookielib)。tkinter(所有Tkinter相关的模块但turtle除外)。turtle的目标用户通常并不真的关心tkinter。 还要注意在 Python 2.6 中,turtle的功能得到了大幅增强。urllib(urllib,urllib2,urlparse,robotparse)。xmlrpc(xmlrpclib,DocXMLRPCServer,SimpleXMLRPCServer)。
其他一些针对标准库模块的改变,未被 PEP 3108 覆盖:
去除了
sets。 请改用内置set()类。清理了
sys模块:移除sys.exitfunc(),sys.exc_clear(),sys.exc_type,sys.exc_value,sys.exc_traceback。 (请注意sys.last_type等仍然保留。)清理了
array.array类型:去除read()和write()方法;改用fromfile()和tofile()。 此外,数组的'c'类型代码已去除 -- 请使用'b'表示字节数据或使用'u'表示 Unicode 字符。清理了
operator模块:移除sequenceIncludes()和isCallable()。清理了
thread模块:去除acquire_lock()和release_lock();改用acquire()和release()。清理了
random模块:移除jumpahead()API。new模块已不复存在。os.tmpnam(),os.tempnam()和os.tmpfile()等函数已被移除并应改用tempfile模块。tokenize模块已被修改以适用于字节串。 主入口点现在是tokenize.tokenize(),而不是 generate_tokens。string.letters及其同类 (string.lowercase和string.uppercase) 已不复存在。 请改用string.ascii_letters等。 (移除string.letters及其同类的原因在于它们具有语言区域专属的行为,对于这些被称为全局“常量”的对象来说不是好主意。)模块
__builtin__被重命名为builtins(移除了下划线,添加了 's')。 大多数全局命名空间中的__builtins__变量保持不变。 要修改内置对象,你应当使用builtins,而不是__builtins__!
PEP 3101: 字符串格式化的新方式¶
一种针对内置字符串格式化操作的新系统替代了
%字符串格式化运算符。 (不过,%运算符仍然受到支持;它将在 Python 3.1 中被弃用并在今后某一时刻从语言特性中移除。) 请参阅 PEP 3101 了解详情。
对异常的修改¶
用于引发和捕获异常的 API 已经过清理并增加了强大的新特性:
PEP 352: 所有异常都必须(直接或间接地)派生自
BaseException。 这是异常层级结构的根对象。 作为推荐方式这并不是新的变化,但 必须 从BaseException继承是新的变化。 (Python 2.6 仍然允许引发经典类,并且不限制你能捕获的异常。) 作为此变化的结果,字符串异常终于真正彻底地死亡了。几乎所有异常实际上都应当派生自
Exception;BaseException仅应当被用作那些仅应当在最高层级中处理的异常的基类,如SystemExit或KeyboardInterrupt。 处理除了后面这一类之外的所有异常的推荐写法是使用exceptException。StandardError已被移除。异常已不再被当作序列来处理。 而应改用
args属性。PEP 3109: 引发异常。 你现在必须使用
raise Exception(args)而不是raise Exception, args。 此外,你不再可以显式地指定回溯;作为替代,如果你 必须 这样做,你可以直接赋值给__traceback__属性(见下文)。PEP 3110: 捕获异常。 你现在必须使用
except SomeException as variable而不是except SomeException, variable。 此外,variable 会在离开except代码块时被显式地删除。PEP 3134: 异常串连。 存在两种情况:隐式串连和显式串连。 当异常在
except或finally处理器代码块中被引发时将发生隐式串连。 通常发生这种情况是由于处理器代码块中存在程序缺陷;我们将其称为 二级 异常。 在这种情况下,(正在处理的)原始异常将被保存为该二级异常的__context__属性。 显式串连则是由以下语法来唤起:raise SecondaryException() from primary_exception
(这里 primary_exception 是产生一个异常对象的任何异常,它可能是在之前被捕获的异常)。 在这种情况下,该原始异常将存储在二级异常的
__cause__属性中。 如果遍历__cause__和__context__属性链时发生了未被处理的异常则会打印回溯信息并为属性链中的每个部分打印单独的回溯信息,原始异常将位于最上面。 (Java 用户可能很了解这样的行为。)PEP 3134: 异常对象现在会将其回溯信息保存为
__traceback__属性。 这意味着一个异常对象现在将包含从属于异常的所有信息,没有什么理由再使用sys.exc_info()(不过后者并未被移除)。一些提示 Windows 载入扩展模块失败的异常消息得到了改进。 例如,
error code 193现在是%1 is not a valid Win32 application。 字符串现在可处理非英语的语言区域。
其他杂项修改¶
运算符与特殊方法¶
现在
!=将返回与==相反的结果,除非==是返回NotImplemented。“未绑定方法”的概念已从语言中移除。 现在当把一个方法作为类属性来引用时,你将得到一个普通函数对象。
__getslice__(),__setslice__()和__delslice__()已被去除。 现在a[i:j]语法形式将被转为a.__getitem__(slice(i, j))(或者当用作赋值或删除的目标时,分别被转为__setitem__()或__delitem__())。PEP 3114: 标准的
next()方法已被重命名为__next__()。__oct__()和__hex__()特殊方法已被移除 -- 现在oct()和hex()将使用__index__()来将参数转换为整数。移除了对
__members__和__methods__的支持。名为
func_X的函数属性已被重命名为使用__X__的形式,在函数属性命名空间中释放这些名称以便作为用户自定义属性。 也就是说,func_closure,func_code,func_defaults,func_dict,func_doc,func_globals,func_name分别被重命名为__closure__,__code__,__defaults__,__dict__,__doc__,__globals__,__name__。__nonzero__()现在为__bool__()。
内置对象¶
PEP 3135: 新的
super()。 现在你可以不带参数地唤起super()这样(假定这发生在定义于class语句内部的常规实例方法中)将会自动选择正确的类和实例。 附带参数时,super()的行为保持不变。PEP 3111:
raw_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()。 原apply(f, args)请改用f(*args)。移除了
callable()。 原callable(f)可以改用isinstance(f, collections.Callable)。operator.isCallable()函数也已不复存在。移除了
coerce()。 由于经典类已不复存在此函数也不再有用处。移除了
execfile()。 原execfile(fn)请改用exec(open(fn).read())。移除了
reduce()。 如果你确实需要它可使用functools.reduce();不过,在百分之 99 的情况下用显式的for循环会有更好的可读性。移除了
reload()。 请使用imp.reload()。移除了
dict.has_key()-- 请改用in运算符。
构建和 C API 的改变¶
由于时间约束,下面 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 已被移除。新的 C API
PyImport_ImportModuleNoBlock(),类似于PyImport_ImportModule()但不会因导入锁而阻塞(改为返回错误)。重命名布尔转换的 C 层级槽位和方法:
nb_nonzero现在改为nb_bool。从 C API 中移除了
METH_OLDARGS和WITH_CYCLE_GC。
性能¶
综合而言 3.0 的改变使得 Python 3.0 运行 pystone 基准测试的速度比 Python 2.5 慢了约 10%。 其中最大的原因可能是移除了针对小整数的特别场景的处理。 虽然存在改进空间,但这将在 3.0 发布之后再进行!
移植到 Python 3.0¶
对于将现有 Python 2.5 或 2.6 源代码移植到 Python 3.0,最佳的策略如下:
(必要前提:)启动良好的测试覆盖。
移植到 Python 2.6。 这应该不会比从 Python 2.x 到 Python 2.(x+1) 的正常移植更麻烦。 请确保所有的测试均能通过。
(仍然使用 2.6:) 打开
-3命令行开关。 这将启用针对将在 3.0 中被移除(或修改)的特性的警告。 再次运行你的测试套件,并修复你收到相关警告的代码直至不再有任何警告,并且所有的测试仍然能通过。对你的源代码树运行
2to3源代码翻译器。 在 Python 3.0 中运行翻译后的结果。 手动修复任何剩余的问题,一至修复到所有的测试再度通过。
不建议尝试编写可不加修改地同时运行于 Python 2.6 和 3.0 的源代码;你将不得不使用一种非常扭曲的代码风格,例如避免 print 语句、元类和许多其他特性。 如果你正在维护需要同时支持 Python 2.6 和 Python 3.0 的库,最佳做法是将上述的步骤 3 修改为编辑源代码的 2.6 版本并再次运行 2to3 翻译器,而不是修改源代码的 3.0 版本。
有关如何将 C 扩展移植到 Python 3.0,请参阅 将扩展模块移植到 Python 3。