幾乎所有的python2程序都需要一些修改才能正常的運行在python3的環境下。為了簡化這個轉換過程,Python3自帶了一個2to3的實用腳本.這個腳本會將python2程序源文件作為輸入,然后自動轉換到python3.但並不是所有內容都可以自動轉換。
print語句
python2中print是一個語句,不論想輸出什么,直接放到print關鍵字后面即可。python3里,print()是一個函數,像其他函數一樣,print()需要你將要輸出的東西作為參數傳給它。
python2 | python3 | 備注 |
---|---|---|
print() | 輸出一個空白行,python3需要調用不帶參數的print() | |
print 1 | print(1) | 輸出一個值,將值傳入print()函數 |
print 1, 2 | print(1,2) | 輸出使用空格分割的兩個值,使用兩個參數調用print() |
print 1, 2, | print(1,2, end=' ') | python2中如果使用一個,作為print結尾,將會用空格分割輸出的結果,然后在輸出一個尾隨的空格,而不輸回車。python3里,把end=' ' 作為一個關鍵字傳給print()可以實現同樣的效果,end默認值為'\n',所以通過重新指定end參數的值,可以取消在末尾輸出回車符號 |
print >> sys.stderr, 1, 2, 3 | print(1, 2, 3, file=sys.stderr | python2中,可以通過>>pipe_name語法,把輸出重定向到一個管道,比如sys.stderr.在python3里,可以通過將管道作為關鍵字參數file的值傳遞給print()完成同樣的功能。 |
UNICODE字符串
python2中有兩種字符串類型:Unicode字符串和非Unicode字符串。Python3中只有一種類型:Unicode字符串。
python2 | python3 | 備注 |
---|---|---|
u'PapayaWhip' | 'PapayaWhip' | python2中的Unicode字符串在python3即為普通字符串 |
ur'PapayaWhip\foo' | r'PapayWhip\foo' | Unicode原始字符串(使用這種字符串,python不會自動轉義反斜線"\")也被替換為普通的字符串,因為在python3里,所有原始字符串都是以unicode編碼的。 |
全局函數UNICODE()
python2有兩個全局函數可以把對象強制轉換成字符串:unicode()把對象轉換成unicode字符串,還有str()把對象轉換為非Unicode字符串。Python3只有一種字符串類型,unicode字符串,所以str()函數即可完成所有的功能。
LONG長整型
python2有非浮點數准備的int和long類型。int類型最大值不能超過sys.maxint,而且這個最大值是平台相關的。可以通過在數字的末尾附上一個L來定義長整型,顯然,它比int類型表示的數字范圍更大。在python3里,只有一種整數類型int,大多數情況下,和python2中的長整型類似。
python2 | python3 | 備注 |
---|---|---|
x = 1000000000000L | x = 1000000000000 | python2中的十進制長整型在python3中被替換為十進制普通整數 |
x = 0xFFFFFFFFFFFFL | x = 0xFFFFFFFFFFFF | python2里的十六進制長整型在python3里被替換為十六進制的普通整數 |
long(x) | int(x) | python3沒有long() |
type(x) is long | type(x) is int | python3用int判斷是否為整型 |
isinstance(x, long) | isinstance(x, int) | int檢查整數類型 |
<>比較運算符
Python2支持<>作為!=的同義詞, python3只支持!=, 不再支持<>
字典類方法HAS_KEY()
Python2中,字典對象has_key()方法測試字典是否包含指定的鍵。python3不再支持這個方法,需要使用in.
返回列表的字典類方法
在python2里,許多字典類方法的返回值是列表。最常用方法有keys, items和values。python3,所有以上方法的返回值改為動態試圖。在一些上下文環境里,這種改變不會產生影響。如果這些方法的返回值被立即傳遞給另外一個函數,而且那個函數會遍歷整個序列,那么以上方法的返回值是列表或視圖並不會產生什么不同。如果你期望獲得一個被獨立尋址元素的列表,那么python3的這些改變將會使你的代碼卡住,因為視圖不支持索引。
python2 | python3 | 備注 |
---|---|---|
a_dictionary.keys() | list(a_dictionary.keys()) | 使用list()將keys 返回值轉換為一個靜態列表 |
a_dictionary.items() | list(a_dictonary.items()) | 將items返回值轉為列表 |
a_dictionary.iterkeys() | iter(a_dictionary.keys()) | python3不再支持iterkeys,使用iter()將keys()的返回值轉換為一個迭代器 |
[i for i in a_dictionary.iterkeys()] | [ i for i in a_dictonary.keys()] | 不需要使用額外的iter(),keys()方法返回的是可迭代的 |
min(a_dictionary.keys()) | no change | 對min(),max(),sum(),list(),tuple(),set(),sorted(),any()和all()同樣有效 |
重命名或重新組織的模塊
從python2到python3,標准庫里的一些模塊已經被重命名。還有一些相互關聯的模塊也被組合或則重新組織,使得這種關聯更有邏輯性。
HTTP
python3中幾個相關的http模塊被組合成一個單獨的包,即http
python2 | python3 | 備注 |
---|---|---|
import httplib | import http.client | http.client模塊實現一個底層的庫,可以用來請求和解析http |
import cookie | import http.cookies | http.cookie提供一個pythonic接口進行cookies操作 |
import cookielib | import http.cookiejar | http.cookiejar可以操作cookies文件 |
import BaseHTTPServer import SimpleHTTPServer import CGIHttpServer | import http.server | http.server實現了一個基本的http服務器 |
URLLIB
python2中用來分析、編碼和獲取URL的模塊,但是比較混亂,python3中,這些模塊被重構,組合成為一個單獨的包,即urllib
| python2 | python3 | 備注 | import urllib | import urllib.request, import urllb.parse, import urllib.error | | import urllib2 | import urllib.request, urllib.error | | import urlparse | import urllib.parse | | import robotparser | import urllib.robotparser | | from urllib import FancyURLopener | from urllib.rquest import FancyURLopener from urllib.parse | |from urllib2 import Request from urllib2 import HTTPError | from urllib.request import Request from urllib.error import HTTPError |
DBM
所有的DBM現在都在一個單獨的包里,即dbm。如果需要其中某個特定的變體,比如GNU DBM,可以導入dbm包中合適的模塊。
python2 | python3 | 備注 |
---|---|---|
import dbm | import dbm.ndbm | |
import gdbm | import dbm.gnu | |
import dbhash | import dbm.bad | |
import dumbdbm | import dbm.dumb | |
import anydbm import whichdb | import dbm |
XMLRPC
XML-RPC是一個通過HTTP協議執行遠程RPC調用的輕重級方法。一些XML_RPC客戶端和XML_RPC服務端的實現庫組合成獨立的包,xmlrpc.
python2 | python3 | 備注 |
---|---|---|
import xmlrpclib | import xmlrpc.client | |
import DocXMLRPCServer import SimpleXMLRPCServer | import xmlrpc.server |
其他模塊
Python2 | python3 | 備注 |
---|---|---|
try: import cStringIO as StringIO except ImportError: import STringIO | import io | |
try: import cPickle as pickle except ImportError: import pickle | import pickle | |
import builtin | import builtins | |
import copy_reg | import copyreg | |
import Queue | import queue | |
import SocketServer | import socketserver | |
import ConfigParser | import configparser | |
import repr | import reprlib | |
import commands | import subprocess |
包內的相對導入
包是由一組相關聯的模塊共同組成的單個實體。在python2的時候,為了實現同一個包內模塊的相互引用,你會使用import foo或者from foo import Bar。Python2解釋器會先在當前目錄里搜索foo.py,然后再去python搜索路徑(sys.path)搜索。在python3里這個過程有一點不同。Python3不會首先在當前路徑搜索,它會直接在Python的搜索路徑里尋找。如果想要包里的一個模塊導入包的另一個模塊,需要顯式的提供兩個模塊的相對路徑。
迭代器方法NEXT()
python2里,迭代器有一個next()方法,用來返回序列的下一項。在python3里同樣成立。但是有一個新的全局的函數next(),它使用一個迭代器作為參數。
python2 | python3 | 備注 |
---|---|---|
anIterator.next() | next(anIterator) | |
a_function_that_returns_an_iterator().next() | next(a_function_that_returns_an_iterator()) | |
class A: def next(self): pass | class A : def next(self): pass | |
class A: def next(self, x, y): pass | no change | |
next = 42 for an_iterator in a_sequence_of_iterators: an_iterator.next() | next =42 for an interator in a_sequence_of_iterators: an_iterator.next() |
全局函數FILTER()
在python2里,filter()方法返回一個列表,這個列表是通過一個返回值為True或False的函數來檢測序列里的每一項的道德。在python3中,filter()函數返回一個迭代器,不再是列表。
python2 | python3 | 備注 |
---|---|---|
filter(a_function, a_sequence) | list(filter(a_function, a_sequence)) | |
list(filter(a_function, a_sequence)) | no change | |
filter(None, a_sequence) | [i for i in a_sequence if i ] | |
for i in filter(None, a_sequence): | no change | |
[i for i in filter(a_function, a_sequence)] | no change |
MAP()
跟filter()的改變一樣,map()函數現在返回一個迭代器,python2中返回一個列表。
python2 | python3 | 備注 |
---|---|---|
map(a_function,'PapayaWhip' | list(map(a_function, 'PapayaWhip')) | |
map(None, 'PapayaWhip' | list('PapayWhip') | |
map(lambda x: x+1, range(42)) | [x+1 for x in range(42)] | |
for i in map(a_function, a_sequence): | no change | |
[i for i in map(a_function, a_sequence)] | no change |
REDUCE()
在python3里,reduce()函數已經從全局名字空間移除,現在被放置在fucntools模塊里。
python2 | python3 | 備注 |
---|---|---|
reduce(a,b,c) | from functools import reduce reduce(a, b, c) |
APPLY()
python2有一個叫做apply()的全局函數,它使用一個函數f和一個列表[a,b,c]作為參數,返回值是f(a,b,c).可以直接調用這個函數,在列表前添加一個星號作為參數傳遞給它來完成同樣的事情。在python3里,apply()函數不再存在;必須使用星號標記。
python2 | python3 | 備注 |
---|---|---|
apply(a_function, a_list_of_args | a_function(*a_list_of_args) | |
apply(a_function, a_list_of_args, a_dictionary_of_named_args) | a_function(*a_list_of_args, **a_dictionary_of_named_args) | |
apply(a_function, a_list_of_args + z) | a_function(*a_list_of_args + z) | |
apply(aModule.a_function, a_list_of_args) | aModule.a_function(*a_list_of_args) |
INTERN() python2里,你可以用intern()函數作用在一個字符串上來限定intern以達到性能優化,python3里,intern()函數轉移到sys模塊里。
python2 | python3 | 備注 |
---|---|---|
intern(aString) | sys.intern(aString) | -------- |
EXEC
就像print語句在python3里變成了一個函數一樣,exec語句也是這樣的。exec()函數使用一個包含任意python代碼的字符串作為參數,然后像執行語句或表達式一樣執行它。exec()跟eval()是相似,但exec()更加強大並具有挑戰性。eval()函數只能執行單獨一條表達式,但是exec()能夠執行多條語句,導入(import),函數聲明-實際上整個python程序的字符串表示也可以。
python2 | python3 | 備注 |
---|---|---|
exec codeString | exec(codeString) | |
exec codeString in a_global_namespace | exec(codeString, a_global_namespace) | |
exec_codeString in a_global_namespace, a_local_namespace | exec(codeString, a_global_namespace, a_local_namespace |
execfile
python2中的execfile語句可以像執行python代碼那樣使用字符串。不同的是exec使用字符串,而execfile使用文件。在python3,execfile語句被去掉了。
REPR
在python2,為了得到一個任意對象的字符串表示,有一種把對象包裝在反引號里(比如x
)的特殊語法。在python3里,這種能力仍然存在,但是你不能再使用反引號獲得這種字符串表示了,需要使用全局函數repr().
python2 | python3 | 備注 |
---|---|---|
x |
repr(x) | |
'PapayaWhip' + 2
|
repr('PapayWhip' + repr(2)) |
TRYEXCEPT語句
python2到python3,捕獲異常的語法有些變化。
Python2 | Python3 | 備注 |
---|---|---|
try: import mymodule except ImportError, e pass | try: import mymodule except ImportError as e: pass | |
try: import mymodule except (RuntimeError, ImportError), e pass | try: import mymodule except(RuntimeError, ImportError) as e: pass | |
try: import mymodule except ImportError: pass | no change | |
try: import mymodule except: pass | no change |
RAISE
python3里,拋出自定義異常的語法有細微的變化。
python2 | python3 | 備注 |
---|---|---|
raise MyException | unchanged | |
raise MyException, 'error message' | raise MyException('error message') | |
raise MyException, 'error message' | raise MyException('error message').with_traceback(a_traceback) | |
raise 'error message' | unsupported |
生成器THROW
在python2里,生成器有一個throw()方法。調用a_generator.throw()會在生成器被暫停的時候拋出異常,然后返回由生成器函數獲取的下一個值。python3中,這一功能仍然可用,但語法有一點不同。
python2 | python3 | 備注 |
---|---|---|
a_generator.throw(MyException) | no change | |
a_generator.throw(MyException, 'error message' | a_generator.throw(MyException('error message')) | |
a_generator.throw('error message') | unsupported |
XRANGE()
python2里,有兩種方法獲得一定范圍內的數字:range(),返回一個列表,還有xrange(),返回一個迭代器。python3 里,range()返回迭代器,xrange()不再存在。
python2 | python3 | 備注 |
---|---|---|
xrange(10) | range(10) | |
a_list = range(10) | a_list= list(range(10)) | |
[i for i in xrange(10)] | [i for i in range(10)] | |
for i in range(10): | no change | |
sum(range(10)) | no change |
RAW_INPUT()和INPUT()
python2有兩個全局函數,用在命令行請求用戶輸入。第一個叫input(),它等待用戶輸入一個python表達式(然后返回結果)。第二個叫做raw_input(),用戶輸入什么他就返回什么。python3 通過input替代了他們。
python2 | python3 | 備注 |
---|---|---|
raw_input() | input | input替代了raw_input |
raw_input('prompt') | input('prompt') | python3仍然支持提示符參數 |
input() | eval(input)) |
函數屬性FUNC_*
python2,函數的代碼可用訪問到函數本身的特殊屬性。python3為了一致性,這些特殊屬性被重命名了。
python2 | python3 | 備注 |
---|---|---|
a_function.func_name | a_function.__name__ | __name__屬性包含了函數的名字 |
a_function.func_doc | a_function.__doc__ | __doc__包含了函數源代碼定義的文檔字符串 |
a_function.func_defaults | a_function.__defaults__ | 是一個保存參數默認值的元組 |
a_function.func_dict | a_function.__dict__ | __dict__屬性是一個支持任意函數屬性的名字空間 |
a_function.func_closure | a_function.__closure__ | __closure__屬性是由cell對象組成的元組,包含了函數對自由變量的綁定 |
a_function.func_globals | a_function.__globals__ | 是對模塊全局名字空間的引用 |
a_function.func_code | a_function.__code__ | 是一個代碼對象,表示編譯后的函數體 |
I/O方法XREADLINES()
python2中,文件對象有一個xreadlines()方法,返回一個迭代器,一次讀取文件的一行。這在for循環中尤其實用。python3中,xreadlines()方法不再可用。
lambda函數
在python2中,可以定義匿名函數lambda函數,通過指定作為參數的元組的元素個數,使這個函數實際上能夠接收多個參數。python2的解釋器把這個元組"解開“成命名參數,然后可以在lambda函數里引用它們。在python3中仍然可以傳遞一個元組為lambda函數的參數。但是python解釋器不會把它當成解析成命名參數。需要通過位置索引來引用每個參數。
python2 | python3 | 備注 |
---|---|---|
lambda (x,): x + f(x) | lambda x1 : x1[0] + f(x1[0]) | 注1 |
lambda (x,y): x + f(y) | lambda x_y : x_y[0] + f(x_y[1]) | 注2 |
lambda (x,(y,z)): x + y + z | lambda x_y_z: x_y_z[0] + x_y_z[1][0]+ x_y_z[1][1] | 注3 |
lambda x,y,z: x+y+z | unchanged | 注4 |
注1:如果定義了一個lambda函數,使用包含一個元素的元組作為參數,python3中,會被轉換成一個包含到x1[0]的引用的lambda函數。x1是2to3腳本基於原來元組里的命名參數自動生成的。
注2:使用含有兩個元素的元組(x,y)作為參數的lambda函數被轉換為x_y,它有兩個位置參數,即x_y[0]和x_y[1]
注3:2to3腳本可以處理使用嵌套命名參數的元組作為參數的lambda函數。產生的結果有點晦澀,但python3下和python2的效果是一樣的。
注4:可以定義使用多個參數的lambda函數。語法在python3同樣有效
特殊的方法屬性
在python2里,類方法可以訪問到定義他們的類對象,也能訪問方法對象本身。im_self是類的實例對象;im_func是函數對象,im_class是類本身。在python3里,這些屬性被重命名,以遵循其他屬性的命名約定。
python2 | python3 |
---|---|
aClassInstance.aClassMethod.im_func | aClassInstance.aClassMethod.__func__ |
aClassInstance.aClassMethod.im_self | aClassInstance.aClassMethod.__self__ |
aClassInstance.aClassMethod.im_class | aClassInstance.aClassMethod.__self__.__class__ |
__NONZERO__特殊方法
在python2里,可以創建自己的類,並使他們能夠在布爾上下文中使用。舉例來說,可以實例化這個類,並把這個實例對象用在一個if語句中。為了實現這個目的,可以定義一個特別的__nonzero__()方法,它的返回值為True或False,當實例對象處在布爾上下文中的時候這個方法就會被調用。在python3中,仍然可以完成同樣的功能,但這個特殊方法的名字改為了__bool__()
比如python2中
class A: def __nonzero__(self): pass
python3中改為: class A: def bool(self): pass
在布爾上下文使用一個類對象時,python3會調用__bool__().
python2中:
class A: def __nonzero__(self, x, y): pass
這種情況python3中不做改變,使用兩個參數的__nonzero__()方法,2to3腳本會假設你定義的這個方法有其他用處,不做修改。
八進制類型
python2和python3,定義八進制數的語法有輕微的改變
python2 | python3 |
---|---|
x= 0755 | x = 0o755 |
SYS.MAXINT
python3中長整型和整型被整合到一起,sys.maxint常量不再精確。但是因為這個值用於檢查特定平台,所以被python3保留,重命名為sys.maxsize.
全局函數CALLABLE()
python2里,可以使用全局函數callable()來檢查一個對象是否可調用,在python3中,這個全局函數被取消了,為了檢查一個對象是否可調用,可以檢查其特殊方法__call__()的存在性。
python2 | python3 |
---|---|
callable(anthing) | hasattr(anything, '__call__') |
全局函數ZIP()
在python2,zip()可以使用任意多個序列作為參數,它返回一個由元組構成的列表。第一個元組包含了每個序列的第一個元素,第二個元組包含了每個序列的第二個元素,依次遞推。在python3中返回一個迭代器,而非列表。
python2 | python3 | note |
---|---|---|
zip(a,b,c) | list(zip(a,b,c) | python3中可以通過list函數遍歷zip()返回的迭代器,形成列表返回 |
d.join(zip(a,b,c)) | no change | 在已經會遍歷所有元素的上下文環境里,zip()本身返回的迭代器能夠正常工作,2to3腳本檢測到后,不再修改 |
STANDARDERROR異常
python2中,StandardError是除了StopIteration,GeneratorExit,KeyboardInterrupt, SystemExit之外所有其他內置異常的基類。python3中StandardError已經被取消了,使用Exception取代。
TYPES模塊中的常量
types模塊里各種各樣的常量能夠幫助你決定一個對象的類型。在python2里,它包含了代表所有基本數據類型的常量,如dict和int。在python3里,這些常量被取消了,只需使用基礎類型的名字來替代。
python2 | python3 |
---|---|
types.UnicodeType | str |
types.StringType | bytes |
types.DictType | dict |
types.IntType | int |
types.LongType | int |
types.ListType | list |
types.NoneType | type(None |
types.BooleanType | bool |
types.BufferType | memoryview |
types.ClassType | type |
types.ComplexType | complex |
types.EllipsisType | type(Ellipsis) |
types.FloatType | float |
types.ObjectType | object |
types.NotImplementedType | type(NotImplemented) |
types.SliceType | slice |
types.TupleType | tuple |
types.TypeType | type |
types.XRangeType | range |
全局函數ISINSTANCE()
isinstance()函數檢查一個對象是否是一個特定類(class)或類型(type)的實例。在python2,可以傳遞一個由類型構成的元組給isinstance(),如果該對象是元組里的任意一種類型,函數返回True. 在python3,依然可以這樣做。
python2 | python3 |
---|---|
isinstance(x, (int, float, int)) | isinstance(x, (int, float)) |
ITERTOOLS模塊
python2.3引入itertools模塊,定義了zip(),map(),filter()的變體,這個變體返回的是迭代器,而非列表。在python3,這些函數返回的本身就是迭代器,所有這些變體函數就取消了。
SYS.EXC_TYPE,SYS.EXC_VALUE,SYS.EXC_TRACEBACK
處理異常的時候,在sys模塊里有三個你可以訪問的變量:sys.exc_type, sys.exc_value, sys.exc_traceback. python3中這三個變量不再存在,使用sys.exc_info替代。
對元組的列表解析
python2,如果需要編寫一個遍歷元組的列表解析,不需要在元組值周圍加上括號。在python3里,這些括號是必需的。
python2 | python3 |
---|---|
[ i for i in 1, 2] | [i for i in (1,2)] |
元類
在python2里,可以通過在類的聲明中定義metaclass參數,或者定義一個特殊的類級別(class-level)__metaclass__屬性,來創建元類。python3中,__metaclass__屬性被取消了。
python2 | python3 | note |
---|---|---|
class C(metaclass=PapayaMeta): pass | unchanged | |
class Whip: __metaclass__ = PapayMeta | class Whip(metaclass=PapayaMeta): pass | |
class C(Whipper, Beater): __metaclass__ = PapayaMeta | class C(Whipper, Beater, metaclass=PapayMeta): pass |
幾乎所有的python2程序都需要一些修改才能正常的運行在python3的環境下。為了簡化這個轉換過程,Python3自帶了一個2to3的實用腳本.這個腳本會將python2程序源文件作為輸入,然后自動轉換到python3.但並不是所有內容都可以自動轉換。
print語句
python2中print是一個語句,不論想輸出什么,直接放到print關鍵字后面即可。python3里,print()是一個函數,像其他函數一樣,print()需要你將要輸出的東西作為參數傳給它。
python2 | python3 | 備注 |
---|---|---|
print() | 輸出一個空白行,python3需要調用不帶參數的print() | |
print 1 | print(1) | 輸出一個值,將值傳入print()函數 |
print 1, 2 | print(1,2) | 輸出使用空格分割的兩個值,使用兩個參數調用print() |
print 1, 2, | print(1,2, end=' ') | python2中如果使用一個,作為print結尾,將會用空格分割輸出的結果,然后在輸出一個尾隨的空格,而不輸回車。python3里,把end=' ' 作為一個關鍵字傳給print()可以實現同樣的效果,end默認值為'\n',所以通過重新指定end參數的值,可以取消在末尾輸出回車符號 |
print >> sys.stderr, 1, 2, 3 | print(1, 2, 3, file=sys.stderr | python2中,可以通過>>pipe_name語法,把輸出重定向到一個管道,比如sys.stderr.在python3里,可以通過將管道作為關鍵字參數file的值傳遞給print()完成同樣的功能。 |
UNICODE字符串
python2中有兩種字符串類型:Unicode字符串和非Unicode字符串。Python3中只有一種類型:Unicode字符串。
python2 | python3 | 備注 |
---|---|---|
u'PapayaWhip' | 'PapayaWhip' | python2中的Unicode字符串在python3即為普通字符串 |
ur'PapayaWhip\foo' | r'PapayWhip\foo' | Unicode原始字符串(使用這種字符串,python不會自動轉義反斜線"\")也被替換為普通的字符串,因為在python3里,所有原始字符串都是以unicode編碼的。 |
全局函數UNICODE()
python2有兩個全局函數可以把對象強制轉換成字符串:unicode()把對象轉換成unicode字符串,還有str()把對象轉換為非Unicode字符串。Python3只有一種字符串類型,unicode字符串,所以str()函數即可完成所有的功能。
LONG長整型
python2有非浮點數准備的int和long類型。int類型最大值不能超過sys.maxint,而且這個最大值是平台相關的。可以通過在數字的末尾附上一個L來定義長整型,顯然,它比int類型表示的數字范圍更大。在python3里,只有一種整數類型int,大多數情況下,和python2中的長整型類似。
python2 | python3 | 備注 |
---|---|---|
x = 1000000000000L | x = 1000000000000 | python2中的十進制長整型在python3中被替換為十進制普通整數 |
x = 0xFFFFFFFFFFFFL | x = 0xFFFFFFFFFFFF | python2里的十六進制長整型在python3里被替換為十六進制的普通整數 |
long(x) | int(x) | python3沒有long() |
type(x) is long | type(x) is int | python3用int判斷是否為整型 |
isinstance(x, long) | isinstance(x, int) | int檢查整數類型 |
<>比較運算符
Python2支持<>作為!=的同義詞, python3只支持!=, 不再支持<>
字典類方法HAS_KEY()
Python2中,字典對象has_key()方法測試字典是否包含指定的鍵。python3不再支持這個方法,需要使用in.
返回列表的字典類方法
在python2里,許多字典類方法的返回值是列表。最常用方法有keys, items和values。python3,所有以上方法的返回值改為動態試圖。在一些上下文環境里,這種改變不會產生影響。如果這些方法的返回值被立即傳遞給另外一個函數,而且那個函數會遍歷整個序列,那么以上方法的返回值是列表或視圖並不會產生什么不同。如果你期望獲得一個被獨立尋址元素的列表,那么python3的這些改變將會使你的代碼卡住,因為視圖不支持索引。
python2 | python3 | 備注 |
---|---|---|
a_dictionary.keys() | list(a_dictionary.keys()) | 使用list()將keys 返回值轉換為一個靜態列表 |
a_dictionary.items() | list(a_dictonary.items()) | 將items返回值轉為列表 |
a_dictionary.iterkeys() | iter(a_dictionary.keys()) | python3不再支持iterkeys,使用iter()將keys()的返回值轉換為一個迭代器 |
[i for i in a_dictionary.iterkeys()] | [ i for i in a_dictonary.keys()] | 不需要使用額外的iter(),keys()方法返回的是可迭代的 |
min(a_dictionary.keys()) | no change | 對min(),max(),sum(),list(),tuple(),set(),sorted(),any()和all()同樣有效 |
重命名或重新組織的模塊
從python2到python3,標准庫里的一些模塊已經被重命名。還有一些相互關聯的模塊也被組合或則重新組織,使得這種關聯更有邏輯性。
HTTP
python3中幾個相關的http模塊被組合成一個單獨的包,即http
python2 | python3 | 備注 |
---|---|---|
import httplib | import http.client | http.client模塊實現一個底層的庫,可以用來請求和解析http |
import cookie | import http.cookies | http.cookie提供一個pythonic接口進行cookies操作 |
import cookielib | import http.cookiejar | http.cookiejar可以操作cookies文件 |
import BaseHTTPServer import SimpleHTTPServer import CGIHttpServer | import http.server | http.server實現了一個基本的http服務器 |
URLLIB
python2中用來分析、編碼和獲取URL的模塊,但是比較混亂,python3中,這些模塊被重構,組合成為一個單獨的包,即urllib
| python2 | python3 | 備注 | import urllib | import urllib.request, import urllb.parse, import urllib.error | | import urllib2 | import urllib.request, urllib.error | | import urlparse | import urllib.parse | | import robotparser | import urllib.robotparser | | from urllib import FancyURLopener | from urllib.rquest import FancyURLopener from urllib.parse | |from urllib2 import Request from urllib2 import HTTPError | from urllib.request import Request from urllib.error import HTTPError |
DBM
所有的DBM現在都在一個單獨的包里,即dbm。如果需要其中某個特定的變體,比如GNU DBM,可以導入dbm包中合適的模塊。
python2 | python3 | 備注 |
---|---|---|
import dbm | import dbm.ndbm | |
import gdbm | import dbm.gnu | |
import dbhash | import dbm.bad | |
import dumbdbm | import dbm.dumb | |
import anydbm import whichdb | import dbm |
XMLRPC
XML-RPC是一個通過HTTP協議執行遠程RPC調用的輕重級方法。一些XML_RPC客戶端和XML_RPC服務端的實現庫組合成獨立的包,xmlrpc.
python2 | python3 | 備注 |
---|---|---|
import xmlrpclib | import xmlrpc.client | |
import DocXMLRPCServer import SimpleXMLRPCServer | import xmlrpc.server |
其他模塊
Python2 | python3 | 備注 |
---|---|---|
try: import cStringIO as StringIO except ImportError: import STringIO | import io | |
try: import cPickle as pickle except ImportError: import pickle | import pickle | |
import builtin | import builtins | |
import copy_reg | import copyreg | |
import Queue | import queue | |
import SocketServer | import socketserver | |
import ConfigParser | import configparser | |
import repr | import reprlib | |
import commands | import subprocess |
包內的相對導入
包是由一組相關聯的模塊共同組成的單個實體。在python2的時候,為了實現同一個包內模塊的相互引用,你會使用import foo或者from foo import Bar。Python2解釋器會先在當前目錄里搜索foo.py,然后再去python搜索路徑(sys.path)搜索。在python3里這個過程有一點不同。Python3不會首先在當前路徑搜索,它會直接在Python的搜索路徑里尋找。如果想要包里的一個模塊導入包的另一個模塊,需要顯式的提供兩個模塊的相對路徑。
迭代器方法NEXT()
python2里,迭代器有一個next()方法,用來返回序列的下一項。在python3里同樣成立。但是有一個新的全局的函數next(),它使用一個迭代器作為參數。
python2 | python3 | 備注 |
---|---|---|
anIterator.next() | next(anIterator) | |
a_function_that_returns_an_iterator().next() | next(a_function_that_returns_an_iterator()) | |
class A: def next(self): pass | class A : def next(self): pass | |
class A: def next(self, x, y): pass | no change | |
next = 42 for an_iterator in a_sequence_of_iterators: an_iterator.next() | next =42 for an interator in a_sequence_of_iterators: an_iterator.next() |
全局函數FILTER()
在python2里,filter()方法返回一個列表,這個列表是通過一個返回值為True或False的函數來檢測序列里的每一項的道德。在python3中,filter()函數返回一個迭代器,不再是列表。
python2 | python3 | 備注 |
---|---|---|
filter(a_function, a_sequence) | list(filter(a_function, a_sequence)) | |
list(filter(a_function, a_sequence)) | no change | |
filter(None, a_sequence) | [i for i in a_sequence if i ] | |
for i in filter(None, a_sequence): | no change | |
[i for i in filter(a_function, a_sequence)] | no change |
MAP()
跟filter()的改變一樣,map()函數現在返回一個迭代器,python2中返回一個列表。
python2 | python3 | 備注 |
---|---|---|
map(a_function,'PapayaWhip' | list(map(a_function, 'PapayaWhip')) | |
map(None, 'PapayaWhip' | list('PapayWhip') | |
map(lambda x: x+1, range(42)) | [x+1 for x in range(42)] | |
for i in map(a_function, a_sequence): | no change | |
[i for i in map(a_function, a_sequence)] | no change |
REDUCE()
在python3里,reduce()函數已經從全局名字空間移除,現在被放置在fucntools模塊里。
python2 | python3 | 備注 |
---|---|---|
reduce(a,b,c) | from functools import reduce reduce(a, b, c) |
APPLY()
python2有一個叫做apply()的全局函數,它使用一個函數f和一個列表[a,b,c]作為參數,返回值是f(a,b,c).可以直接調用這個函數,在列表前添加一個星號作為參數傳遞給它來完成同樣的事情。在python3里,apply()函數不再存在;必須使用星號標記。
python2 | python3 | 備注 |
---|---|---|
apply(a_function, a_list_of_args | a_function(*a_list_of_args) | |
apply(a_function, a_list_of_args, a_dictionary_of_named_args) | a_function(*a_list_of_args, **a_dictionary_of_named_args) | |
apply(a_function, a_list_of_args + z) | a_function(*a_list_of_args + z) | |
apply(aModule.a_function, a_list_of_args) | aModule.a_function(*a_list_of_args) |
INTERN() python2里,你可以用intern()函數作用在一個字符串上來限定intern以達到性能優化,python3里,intern()函數轉移到sys模塊里。
python2 | python3 | 備注 |
---|---|---|
intern(aString) | sys.intern(aString) | -------- |
EXEC
就像print語句在python3里變成了一個函數一樣,exec語句也是這樣的。exec()函數使用一個包含任意python代碼的字符串作為參數,然后像執行語句或表達式一樣執行它。exec()跟eval()是相似,但exec()更加強大並具有挑戰性。eval()函數只能執行單獨一條表達式,但是exec()能夠執行多條語句,導入(import),函數聲明-實際上整個python程序的字符串表示也可以。
python2 | python3 | 備注 |
---|---|---|
exec codeString | exec(codeString) | |
exec codeString in a_global_namespace | exec(codeString, a_global_namespace) | |
exec_codeString in a_global_namespace, a_local_namespace | exec(codeString, a_global_namespace, a_local_namespace |
execfile
python2中的execfile語句可以像執行python代碼那樣使用字符串。不同的是exec使用字符串,而execfile使用文件。在python3,execfile語句被去掉了。
REPR
在python2,為了得到一個任意對象的字符串表示,有一種把對象包裝在反引號里(比如x
)的特殊語法。在python3里,這種能力仍然存在,但是你不能再使用反引號獲得這種字符串表示了,需要使用全局函數repr().
python2 | python3 | 備注 |
---|---|---|
x |
repr(x) | |
'PapayaWhip' + 2
|
repr('PapayWhip' + repr(2)) |
TRYEXCEPT語句
python2到python3,捕獲異常的語法有些變化。
Python2 | Python3 | 備注 |
---|---|---|
try: import mymodule except ImportError, e pass | try: import mymodule except ImportError as e: pass | |
try: import mymodule except (RuntimeError, ImportError), e pass | try: import mymodule except(RuntimeError, ImportError) as e: pass | |
try: import mymodule except ImportError: pass | no change | |
try: import mymodule except: pass | no change |
RAISE
python3里,拋出自定義異常的語法有細微的變化。
python2 | python3 | 備注 |
---|---|---|
raise MyException | unchanged | |
raise MyException, 'error message' | raise MyException('error message') | |
raise MyException, 'error message' | raise MyException('error message').with_traceback(a_traceback) | |
raise 'error message' | unsupported |
生成器THROW
在python2里,生成器有一個throw()方法。調用a_generator.throw()會在生成器被暫停的時候拋出異常,然后返回由生成器函數獲取的下一個值。python3中,這一功能仍然可用,但語法有一點不同。
python2 | python3 | 備注 |
---|---|---|
a_generator.throw(MyException) | no change | |
a_generator.throw(MyException, 'error message' | a_generator.throw(MyException('error message')) | |
a_generator.throw('error message') | unsupported |
XRANGE()
python2里,有兩種方法獲得一定范圍內的數字:range(),返回一個列表,還有xrange(),返回一個迭代器。python3 里,range()返回迭代器,xrange()不再存在。
python2 | python3 | 備注 |
---|---|---|
xrange(10) | range(10) | |
a_list = range(10) | a_list= list(range(10)) | |
[i for i in xrange(10)] | [i for i in range(10)] | |
for i in range(10): | no change | |
sum(range(10)) | no change |
RAW_INPUT()和INPUT()
python2有兩個全局函數,用在命令行請求用戶輸入。第一個叫input(),它等待用戶輸入一個python表達式(然后返回結果)。第二個叫做raw_input(),用戶輸入什么他就返回什么。python3 通過input替代了他們。
python2 | python3 | 備注 |
---|---|---|
raw_input() | input | input替代了raw_input |
raw_input('prompt') | input('prompt') | python3仍然支持提示符參數 |
input() | eval(input)) |
函數屬性FUNC_*
python2,函數的代碼可用訪問到函數本身的特殊屬性。python3為了一致性,這些特殊屬性被重命名了。
python2 | python3 | 備注 |
---|---|---|
a_function.func_name | a_function.__name__ | __name__屬性包含了函數的名字 |
a_function.func_doc | a_function.__doc__ | __doc__包含了函數源代碼定義的文檔字符串 |
a_function.func_defaults | a_function.__defaults__ | 是一個保存參數默認值的元組 |
a_function.func_dict | a_function.__dict__ | __dict__屬性是一個支持任意函數屬性的名字空間 |
a_function.func_closure | a_function.__closure__ | __closure__屬性是由cell對象組成的元組,包含了函數對自由變量的綁定 |
a_function.func_globals | a_function.__globals__ | 是對模塊全局名字空間的引用 |
a_function.func_code | a_function.__code__ | 是一個代碼對象,表示編譯后的函數體 |
I/O方法XREADLINES()
python2中,文件對象有一個xreadlines()方法,返回一個迭代器,一次讀取文件的一行。這在for循環中尤其實用。python3中,xreadlines()方法不再可用。
lambda函數
在python2中,可以定義匿名函數lambda函數,通過指定作為參數的元組的元素個數,使這個函數實際上能夠接收多個參數。python2的解釋器把這個元組"解開“成命名參數,然后可以在lambda函數里引用它們。在python3中仍然可以傳遞一個元組為lambda函數的參數。但是python解釋器不會把它當成解析成命名參數。需要通過位置索引來引用每個參數。
python2 | python3 | 備注 |
---|---|---|
lambda (x,): x + f(x) | lambda x1 : x1[0] + f(x1[0]) | 注1 |
lambda (x,y): x + f(y) | lambda x_y : x_y[0] + f(x_y[1]) | 注2 |
lambda (x,(y,z)): x + y + z | lambda x_y_z: x_y_z[0] + x_y_z[1][0]+ x_y_z[1][1] | 注3 |
lambda x,y,z: x+y+z | unchanged | 注4 |
注1:如果定義了一個lambda函數,使用包含一個元素的元組作為參數,python3中,會被轉換成一個包含到x1[0]的引用的lambda函數。x1是2to3腳本基於原來元組里的命名參數自動生成的。
注2:使用含有兩個元素的元組(x,y)作為參數的lambda函數被轉換為x_y,它有兩個位置參數,即x_y[0]和x_y[1]
注3:2to3腳本可以處理使用嵌套命名參數的元組作為參數的lambda函數。產生的結果有點晦澀,但python3下和python2的效果是一樣的。
注4:可以定義使用多個參數的lambda函數。語法在python3同樣有效
特殊的方法屬性
在python2里,類方法可以訪問到定義他們的類對象,也能訪問方法對象本身。im_self是類的實例對象;im_func是函數對象,im_class是類本身。在python3里,這些屬性被重命名,以遵循其他屬性的命名約定。
python2 | python3 |
---|---|
aClassInstance.aClassMethod.im_func | aClassInstance.aClassMethod.__func__ |
aClassInstance.aClassMethod.im_self | aClassInstance.aClassMethod.__self__ |
aClassInstance.aClassMethod.im_class | aClassInstance.aClassMethod.__self__.__class__ |
__NONZERO__特殊方法
在python2里,可以創建自己的類,並使他們能夠在布爾上下文中使用。舉例來說,可以實例化這個類,並把這個實例對象用在一個if語句中。為了實現這個目的,可以定義一個特別的__nonzero__()方法,它的返回值為True或False,當實例對象處在布爾上下文中的時候這個方法就會被調用。在python3中,仍然可以完成同樣的功能,但這個特殊方法的名字改為了__bool__()
比如python2中
class A: def __nonzero__(self): pass
python3中改為: class A: def bool(self): pass
在布爾上下文使用一個類對象時,python3會調用__bool__().
python2中:
class A: def __nonzero__(self, x, y): pass
這種情況python3中不做改變,使用兩個參數的__nonzero__()方法,2to3腳本會假設你定義的這個方法有其他用處,不做修改。
八進制類型
python2和python3,定義八進制數的語法有輕微的改變
python2 | python3 |
---|---|
x= 0755 | x = 0o755 |
SYS.MAXINT
python3中長整型和整型被整合到一起,sys.maxint常量不再精確。但是因為這個值用於檢查特定平台,所以被python3保留,重命名為sys.maxsize.
全局函數CALLABLE()
python2里,可以使用全局函數callable()來檢查一個對象是否可調用,在python3中,這個全局函數被取消了,為了檢查一個對象是否可調用,可以檢查其特殊方法__call__()的存在性。
python2 | python3 |
---|---|
callable(anthing) | hasattr(anything, '__call__') |
全局函數ZIP()
在python2,zip()可以使用任意多個序列作為參數,它返回一個由元組構成的列表。第一個元組包含了每個序列的第一個元素,第二個元組包含了每個序列的第二個元素,依次遞推。在python3中返回一個迭代器,而非列表。
python2 | python3 | note |
---|---|---|
zip(a,b,c) | list(zip(a,b,c) | python3中可以通過list函數遍歷zip()返回的迭代器,形成列表返回 |
d.join(zip(a,b,c)) | no change | 在已經會遍歷所有元素的上下文環境里,zip()本身返回的迭代器能夠正常工作,2to3腳本檢測到后,不再修改 |
STANDARDERROR異常
python2中,StandardError是除了StopIteration,GeneratorExit,KeyboardInterrupt, SystemExit之外所有其他內置異常的基類。python3中StandardError已經被取消了,使用Exception取代。
TYPES模塊中的常量
types模塊里各種各樣的常量能夠幫助你決定一個對象的類型。在python2里,它包含了代表所有基本數據類型的常量,如dict和int。在python3里,這些常量被取消了,只需使用基礎類型的名字來替代。
python2 | python3 |
---|---|
types.UnicodeType | str |
types.StringType | bytes |
types.DictType | dict |
types.IntType | int |
types.LongType | int |
types.ListType | list |
types.NoneType | type(None |
types.BooleanType | bool |
types.BufferType | memoryview |
types.ClassType | type |
types.ComplexType | complex |
types.EllipsisType | type(Ellipsis) |
types.FloatType | float |
types.ObjectType | object |
types.NotImplementedType | type(NotImplemented) |
types.SliceType | slice |
types.TupleType | tuple |
types.TypeType | type |
types.XRangeType | range |
全局函數ISINSTANCE()
isinstance()函數檢查一個對象是否是一個特定類(class)或類型(type)的實例。在python2,可以傳遞一個由類型構成的元組給isinstance(),如果該對象是元組里的任意一種類型,函數返回True. 在python3,依然可以這樣做。
python2 | python3 |
---|---|
isinstance(x, (int, float, int)) | isinstance(x, (int, float)) |
ITERTOOLS模塊
python2.3引入itertools模塊,定義了zip(),map(),filter()的變體,這個變體返回的是迭代器,而非列表。在python3,這些函數返回的本身就是迭代器,所有這些變體函數就取消了。
SYS.EXC_TYPE,SYS.EXC_VALUE,SYS.EXC_TRACEBACK
處理異常的時候,在sys模塊里有三個你可以訪問的變量:sys.exc_type, sys.exc_value, sys.exc_traceback. python3中這三個變量不再存在,使用sys.exc_info替代。
對元組的列表解析
python2,如果需要編寫一個遍歷元組的列表解析,不需要在元組值周圍加上括號。在python3里,這些括號是必需的。
python2 | python3 |
---|---|
[ i for i in 1, 2] | [i for i in (1,2)] |
元類
在python2里,可以通過在類的聲明中定義metaclass參數,或者定義一個特殊的類級別(class-level)__metaclass__屬性,來創建元類。python3中,__metaclass__屬性被取消了。
python2 | python3 | note |
---|---|---|
class C(metaclass=PapayaMeta): pass | unchanged | |
class Whip: __metaclass__ = PapayMeta | class Whip(metaclass=PapayaMeta): pass | |
class C(Whipper, Beater): __metaclass__ = PapayaMeta | class C(Whipper, Beater, metaclass=PapayMeta): pass |