这个附录包含一个Python 2和Python 3的不一样之处列表以及能不用2to3转换同时在Python 2和Python 3下运行的示例代码。html
这个列表是不完整的。在这里列出的只有不包括bug修复的策划变化,即便如此也可能有意外的遗漏。python
2to3 fixer ☑ six support ☐express
Python 2的内置apply()在Python 3已经被移除。它用于调用一个函数,但因为你能够直接调用函数它并无什么用并从Python 2.3起被废弃了。没有替代方案。app
2to3 fixer ☑ six support ☐编辑器
Python 2的buffer()内置函数被Python 3的类memoryview取代了。他们是不彻底兼容,因此2to3除非你显示指定buffer固定器不然不会修改这个。函数
这个代码能不用2to3转换在Python 2和Python 3同时运行:测试
>>> import sys >>> if sys.version_info > (3,): ... buffer = memoryview >>> b = buffer('yay!'.encode()) >>> len(b) 4
2to3 fixer ☑ six support ☑ui
Python 2的内置callable()在Python 3.0被移除,可是在Python 3.2从新引入。若是你须要支持Python 3.1你能够用偿试在try的监视下调用对象并在它不能调用时捕捉到一个TypeError。spa
若是你须要不用它来了解对象是否可调用,有几种Python 3的解决方案:.net
>>> def afunction(): ... pass >>> any("__call__" in klass.__dict__ for ... klass in type(afunction).__mro__) True >>> import collections >>> isinstance(afunction, collections.Callable) True
若是你须要代码能不用2to3转换同时在Python 2和Python 3下运行,你能够用这个:
>>> hasattr(bool, '__call__') True
six模块也定义了一个在Python 3下使用的callable函数。
2to3 fixer ☐ six support ☐
在Python 2有两种类型的类,“旧式”和“新式”。“旧式”类已经在Python 3中被移除了。
另见使用新式的类
2to3 fixer ☐ six support ☐
Python 2内置cmp()已经在Python 3.0.1中被移除了,虽然它仍错误地留在了Python 3.0。它主要用于定义__cmp__比较方法或者做为cmp的参数传给.sort(),而且对它的支持也一样在Python 3被移除了。
若是你须要cmp()你能够像这样定义它:
def cmp(a, b): return (a > b) - (a < b)
更多信息见Unorderable类型、__cmp__和cmp。
2to3 fixer ☐ six support ☐
coerce()内置函数和__coerce__方法在Python 3中已经被移除。coerce()将根据Python算术运行符的强制转换规则转换数字参数而且只在引入新数字类型的Python早期版本有用。没有在Python 3中的替代方式;强制转换应该被数字运行符方法代替来作。
2to3 fixer ☑ six support ☐
在Python 2字典有用迭代器代替列表的iterkeys()、 itervalues() 和iteritems()方法。在Python 3标准的keys()、 values() 和items()返回字典视图,字典视图是一个迭代器,因此迭代器变种变得毫无心义并被移除了。
若是你须要不用2to3转换同时支持Python 2和Python 3而且你必须使用迭代器方法,你能够经过try/except来使用它:
>>> d = {'key1': 'value1', ... 'key2': 'value2', ... 'key3': 'value3', ... } >>> try: ... values = d.itervalues() ... except AttributeError: ... values = d.values() >>> isinstance(values, list) False >>> for value in values: ... print(value) value3 value2 value1
此外,字典的has_key()取消了。使用in操做符来代替。
2to3 fixer ☑ six support ☐
在Python 2捕获异常的语法已经人:
except (Exception1, Exception2), target:
改为了明了的Python 3语法:
except (Exception1, Exception2) as target:
其余不一样是目标是能够是元组的时间不长了而且字符串异常已经取消。2to3将会转换除了字符串异常全部的这些。
两种语法都能在Python 2.6和Python 2.7下工做,可是若是你须要不用2to3转换在更早版本下执行,你能够经过sys.exc_info()来获取异常对象:
>>> import sys >>> try: ... raise Exception("Something happened") ... except Exception: ... e = sys.exc_info()[1] ... print(e.args[0]) Something happened
2to3 fixer ☑ six support ☐
在Python 2下异常对象是可能迭代和索引的:
>>> e = Exception('arg1', 'arg2') >>> e[1]' arg2' >>> for a in e: ... print a ... arg1 arg2
在Python 3下你必需要用args属性,这一样能在Python 2下工做。
>>> e = Exception('arg1', 'arg2') >>> e.args[1] 'arg2' >>> for a in e.args: ... print a ... arg1 arg2
还有一个异常的message属性在Python 2.5被引进,可是它在Python 2.6就已经被废弃了,因此它不像是你会用的。
2to3 fixer ☑ six support ☑
在Python 2下exec是这个语句:
>>> g_dict={} >>> l_dict={} >>> exec "v = 3" in g_dict, l_dict >>> l_dict['v'] 3
在Python 3下exec是一个函数:
>>> g_dict={} >>> l_dict={} >>> exec("v = 3", g_dict, l_dict) >>> l_dict['v'] 3
Python 3语法不用全局和局部字典的话也一样能够在Python 2下工做:
>>> exec("v = 3") >>> v 3
若是你须要传递全局或者局部字典你须要定义一个带有两个实现的自定义函数,一个给Python 2,另外一个给Python 3。像往常同样six包含一个这个的一个优秀实现叼着exec_()。
2to3 fixer ☑ six support ☐
Pyhton 2的execfile语句在Python 3已经取消了。做为了一个替代,你能够打开一个文件并读取内容:
exec(open(thefile).read())
这个能够在全部的Python版本工做。
2to3 fixer ☐ six support ☐
在Python 2有file内置类型。在Python 3这被多种文件类型取货代了。大家常常看到Python 2使用file(pathname)的代码在Python 3是失败的。使用open(pathname)来替换这个用例。
若是你须要在Python 3下测试类型,能够查检io.IOBase来替代file。
2to3 fixer ☑ six support ☐
在Python 2下filter()返回一个列表,而在Python 3它返回一个迭代器。2to3在有些状况下会用list()来包裹filter()的调用,以确保结果一直是一个列表。若是你须要不使用2to3转换同时支持Python 2和Python 3而且须要要结果是一个列表,你能够这样作。
2to3 fixer ☑ six support ☐
在Python 2,若是你有一个叫着mypackage的包而且它包含一个叫着csv.py的模块,它将会覆盖标准库的csv模块。在mypackage里的import csv代码将会导入本地文件,从标准库中导入将会变得棘手。
在Python 3,这已经改了,因此import csv会从标准库导入,导入本地的csv.py文件你须要写成from . import csv而且from csv import my_csv须要被改为from .csv import my_csv。这些被叫着“相对导入”,而且也有一个语言来从上一级模块导入:from .. import csv。
若是你不用2to3同时支持Python 2和Python 3,from .和 from ..语法和from __future__ import absolute_import语句起从Python 2.5就能够用了,from __future__ import absolute_import语句能修改这个行为成Python 3的行为。
若是你须要支持Python 2.4或者更新的版本,你必需要讲清楚整个包名,全部import csv变成from mypkg import csv而且from csv import my_csv变成from mypckg.csv import my_csv。为了清晰和可读性,我会尽量避免相对引用而且老是讲清楚完整路径。
2to3会检查你的引用是否是本地的并修改他们。
2to3 fixer ☐ six support ☐
在Python 2做为缩进一个tab等于八个空格,因此你能够用tab来缩进行一行,并在下一行使用八个空格。若是你用的编辑器把tab扩展成非八空格的话,这将是混乱的。
在Python 3一个tab只等于另外一个tab。这意味着每个缩进等级必须是一致地使用tab或者空格。若是你有一个缩进块有时使用tab有时候使用空的文件,你将得来到一个错误TabError: inconsistent use of tabs and spaces inindentation。
解决方法固然是去除不一致性。
2to3 fixer ☑ six support ☐
在Python下有从stdin获取字符串的raw_input()和从stdin获取值并对其进行评估的input()。后一个函数由于不是颇有用,在Python 3中被移除了,而后raw_input()被重命名成input()。
>>> eval(input('Type in an expression: ')) 'Type in an expression: ' 1+2 3
若是你的代码须要不通过2to3转换同时在Python 2和Python 3下执行,你能够有条件地把input()设置成raw_input():
>>> try: ... input = raw_input ... except NameError: ... pass >>> input('Type in a string: ') Type in a string: It works! 'It works!'
2to3 fixer ☐ six support ☐
在Python 2,两个整数相除的结果是整数;换句话说3/2返回1。在Python 3整数相除老是返回一个浮点数。因此3/2会返回1.5,4/2会返回2.0。
若是你想旧的行为你应该使用浮点除法运算符//来替代,这个从Python 2.2开始能够用。若是你须要不用2to3转换同时支持Python 2和Python 3,下面的__future__ import works从Python 2.2起可用,它可以容许新的行为可用 :
>>> from __future__ import division >>> 1/2 0.5
另见 当除以整数时用//代替/
2to3 fixer ☐ six support ☑ (partial)
Python 2有两个整数类型int和long。这些在Python 3被统一了,因此如今只有一种类型,int。这意味着下面的代码在Python 3会失败:
>>> 1L 1L >>> long(1) 1L
在Python 2至关常常地你须要声明一个整数是long。若是你这么作而且须要不经过2to3转换代码能同时在Python 2和Python 3下运行,下面的代码能够作到:
>>> import sys >>> if sys.version_info > (3,): ... long = int >>> long(1) 1L
然而,表达一直都是不一样的,因此文档测试会失败。
若是你须要检查某物是否是一个数字,在Python 2下你须要分别检查int和long,但在Python 3下只须要int。作这个的最好办法下根据不一样的Python版本设置一个integer_types元组并分别测试。six包含这个:
>>> import sys >>> if sys.version_info < (3,): ... integer_types = (int, long,) ... else: ... integer_types = (int,) >>> isinstance(1, integer_types) True
2to3 fixer ☐ six support ☐
在Python 2下map()返回一个列表,然而在Python 3它返回一个迭代器。2to3在一些状况下会在map()调用的周围调用list()以确保结果是一个列表。若是你须要代码不经过2to3转换能同时在Python 2和Python 3下运行而且你须要结果是一个列表,你也可能两样作这个。
在Python 2下map()会持续到最长的可迭代参数耗尽,另外一个参数会用None来扩展。
>>> def fun(a, b): ... if b is not None: ... return a - b ... return -a >>> map(fun, range(5), [3,2,1]) [-3, -1, 1, -3, -4]
在Python 3下map()取代的是在最短的参数那中止。若是你想要在Python 3中使用Python 2的行为,你可使用starmap()和zip_longest()的组合。
>>> from itertools import starmap, zip_longest >>> def fun(a, b): ... if b is not None: ... return a - b ... return -a >>> list(starmap(fun, zip_longest(range(5), [3,2,1]))) [-3, -1, 1, -3, -4]
Python 2的map()会接受None做为它的函数参数,这里它会仅仅返回传入的对象。像这样转换map()成zip()不是特别有用,而且在Python 3这能工做的时间不长了。然而一些代码是依赖这个行为的,你可使用下面的函数来做为Python 2的map替代者。
from itertools import starmap, zip_longest def map(func, *iterables): zipped = zip_longest(*iterables) if func is None: # No need for a NOOP lambda here return zipped return starmap(func, zipped)
2to3 fixer ☑ six support ☑
在Python 2使用__metaclass__来指定元类。在Python 3反而是在类定义传入一个元类参数。不使用2to3转换来在Python 2和Python 3中支持元类须要你匆匆忙忙建立一个类。若是你想作这个,我强烈建议使用six模块,它有一个很是使人满意的_metaclass()函数。
2to3 fixer ☑ six support ☑
在Python 2你能够经过调用iterators.next()方法从迭代器获取一下结果。在Python 3这被一个内置的next()取代。
若是你须要代码不经过2to3转换同时在Python 2和Python 3下运行,你能够写一函数在Python 2下调用iterator.next()在Python 3下调用next(iterator)。six模块包含这种函数,叫着next(iterator)。
2to3 fixer ☐ six support ☐
在Python 2你能够作参数解包:
>>> def unpacks(a, (b, c)): ... return a,b,c >>> unpacks(1, (2,3)) (1, 2, 3)
Python 3不支持这个,因此你须要用你本身的解包来作:
>>> def unpacks(a, b): ... return a,b[0],b[1] >>> unpacks(1, (2,3)) (1, 2, 3)
2to3 fixer ☑ six support ☑
Python 2的print语句在Python 3是一个函数。若是你须要不使用2to3转换在Python 2和Python 3下跑一样的代码,有多种技巧能够作到这个。这个在支持print()函数里讨论。
2to3 fixer ☑ six support ☑
在Python 2下raise语句的语法是:
raise E, V, T
这里E是一个字符串、异常类或者一个异常实例,在E是一个类或者字符串的状况下V是一个可选的异常值,T是一个你想到从不一样于如今代码的地方追踪的追踪对象。在Python 3这变成了:
raise E(V).with_traceback(T)
由于使用Python 2语法,值和追踪是可选的。不带追踪变量的这个语法是:
raise E(V)
这能够在全部的Python版本工做。很常常地你须要追踪参数,可是若是你作了并须要写出不用2to3能在Python 2和Python 3运行的代码,你须要建立一个不一样的带有E、V和T参数的函数而且这个函数在Python 2和Python 3有不一样的实现。six模块对这个很好的实现,叫着reraise()。
2to3 fixer ☑ six support ☑
在Python 2下range()返回一个列表,xrange()只在须要时生成范围内的项目以节省内存。
在Python 3,range()取消了,而且xrange()被重命名成range()。在Python 3.2及以后的版本增长了range()对象的切片支持。
2to3在一些状况下会在调用range()的周围放上一个list()调用,以确保结果是一个列表。若是你须要代码不用2to3转换在Python 2和Python2下能同时运行而且你须要结果是一个列表,你也能够一样这样作。
你能够从six模块导入xrange()来确保你能同时在Python 2和Python 3下获得这个迭代器变种。
2to3 fixer ☑ six support ☐
在Python 2你能够经过反撇号包围来生成一个表达式的字符串表示:
>>> `sorted` '<built-in function sorted>' >>> `2+3` '5'
这个语法的惟一用途是让新手困惑并混淆Python。它在Python 3已经被移除了,由于内置的repr()正好作了一样的事。
>>> repr(sorted)' <built-in function sorted>' >>> repr(2+3) '5'
2to3 fixer ☐ six support ☐
在Python 3中round的行为已经变了。在Python 2中途状况的凑整老是远离零,而且round()老是返回一个浮点数。
>>> round(1.5) 2.0 >>> round(2.5) 3.0 >>> round(10.0/3, 0) 3.0
在Python 3中途状况的凑整如今老是朝向最接近的偶数。这是标准作法,由于它使得一个均匀分布的集合凑整达到平均值。
第二个参数是限制小数的数量,当不用第二个参数调用时round()在Python 3中返回一个整数。若是你传进一个参数来设置凑整的小数数量,返回值会变成和未凑整值相同的类型。即便你传入的是一个零这也是正确的。
>>> round(1.5) 2 >>> round(2.5) 2 >>> round(10.0/3, 0) 3.0
若是你须要Python 2的行为,你可使用下面的方法:
>>> import math >>> def my_round(x, d=0): ... p = 10 ** d ... return float(math.floor((x * p) + math.copysign(0.5, x)))/p >>> my_round(1.5) 2.0 >>> my_round(2.5) 3.0 >>> my_round(10.0/3, 0) 3.0
2to3 fixer ☐ six support ☐
在Python 1你须要用__getslice__和__setslice__切片方法来让你的对象支持像foo[3:7]这样的切片操做。这些被废弃了可是Python 2一直仍是支持。Python 3移除了切片方法的支持,因此你须要扩展__getitem__、__setitem__ 和__delitem__而不是切片对象支持。
>>> class StrawberryTart(object): ... ... def __getitem__(self, n): ... """An example of how to use slice objects""" ... if isinstance(n, slice): ... # Expand the slice object using range() ... # to a maximum of eight items .... return [self[x] for x in ... range(*n.indices(8))] ... ... # Return one item of the tart ... return 'A slice of StrawberryTart with ' \ ... 'not so much rat in it.' ... >>> tart = StrawberryTart() >>> tart[5:6] ['A slice of StrawberryTart with not so much rat in it.']
2to3 fixer ☐ six support ☐
在Python 2列表的.sort()方法和内置的sorted()都带cmp和key这两个参数。在Python 3只支持key参数。没有固定器来作这个,因此你须要在Python 2代码中修改。
更多信息见当排序时,使用key来代替cmp。
2to3 fixer ☑ six support ☐
Python 2有一个在Python 3已经被移除的叫做StandardError的异常类。使用Exception来替代它。
2to3 fixer ☑ six support ☑
Python 2有两种字符串类型;str和unicode。Python 3只有一个;str,可是此外它还有一个bytes类型来处理二进制数据。更的信息见单独的二进制数据和字符串和更多的字节、字符串和Unicode。
附注:
[1] | http://pypi.python.org/pypi/six |
本文地址:http://my.oschina.net/soarwilldo/blog/533438
在湖闻樟注:
原文http://python3porting.com/differences.html