python2 與 python3的區別
幾乎所有的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 |