1. 程式人生 > >python2 與 python3的區別

python2 與 python3的區別

原文出自

幾乎所有的python2程式都需要一些修改才能正常的執行在python3的環境下。為了簡化這個轉換過程,Python3自帶了一個2to3的實用指令碼.這個指令碼會將python2程式原始檔作為輸入,然後自動轉換到python3.但並不是所有內容都可以自動轉換。

print語句

python2中print是一個語句,不論想輸出什麼,直接放到print關鍵字後面即可。python3裡,print()是一個函式,像其他函式一樣,print()需要你將要輸出的東西作為引數傳給它。

python2 python3 備註
print 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 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