生成器的throw方法# 在Python 2裏,生成器有一個throw()方法。調用a_generator.throw()會在生成器被暫停的時候拋出一個異常,而後返回由生成器函數獲取的下一個值。在Python 3裏,這種功能仍然可用,可是語法上有一點不一樣。app
Notes Python 2 Python 3 ① a_generator.throw(MyException) no change ② a_generator.throw(MyException,'error message') a_generator.throw(MyException('error message')) ③ a_generator.throw('error message') unsupported 最簡單的形式下,生成器拋出不帶用戶自定義錯誤信息的異常。這種狀況下,從Python 2到Python 3語法上沒有變化 。 若是生成器拋出一個帶用戶自定義錯誤信息的異常,你須要將這個錯誤信息字符串(error string)傳遞給異常類來以實例化它。 Python 2還支持拋出只有異常信息的異常。Python 3不支持這種語法,而且2to3會顯示一個警告信息,告訴你須要手動地來修復這處代碼。 全局函數xrange()# 在Python 2裏,有兩種方法來得到必定範圍內的數字:range(),它返回一個列表,還有range(),它返回一個迭代器。在Python 3裏,range()返回迭代器,xrange()再也不存在了。函數
Notes Python 2 Python 3 ① xrange(10) range(10) ② a_list = range(10) a_list = list(range(10)) ③ [i for iin xrange(10)] [i for iin range(10)] ④ for i in range(10): no change ⑤ sum(range(10)) no change 在最簡單的狀況下,2to3會簡單地把xrange()轉換爲range()。 若是你的Python 2代碼使用range(),2to3不知道你是否須要一個列表,或者是否一個迭代器也行。出於謹慎,2to3可能會報錯,而後使用list()把range()的返回值強制轉換爲列表類型。 若是在列表解析裏有xrange()函數,就沒有必要將其返回值轉換爲一個列表,由於列表解析對迭代器一樣有效。 相似的,for循環也能做用於迭代器,因此這裏也沒有改變任何東西。 函數sum()能做用於迭代器,因此2to3也沒有在這裏作出修改。就像返回值爲視圖(view)而再也不是列表的字典類方法同樣,這一樣適用於min(),max(),sum(),list(),tuple(),set(),sorted(),any(),all()。 全局函數raw_input()和input()# Python 2有兩個全局函數,用來在命令行請求用戶輸入。第一個叫作input(),它等待用戶輸入一個Python表達式(而後返回結果)。第二個叫作raw_input(),用戶輸入什麼它就返回什麼。這讓初學者很是困惑,而且這被普遍地看做是Python語言的一個「肉贅」(wart)。Python 3經過重命名raw_input()爲input(),從而切掉了這個肉贅,因此如今的input()就像每一個人最初期待的那樣工做。編碼
Notes Python 2 Python 3 ① raw_input() input() ② raw_input('prompt') input('prompt') ③ input() eval(input()) 最簡單的形式,raw_input()被替換成input()。 在Python 2裏,raw_input()函數能夠指定一個提示符做爲參數。Python 3裏保留了這個功能。 若是你真的想要請求用戶輸入一個Python表達式,計算結果,能夠經過調用input()函數而後把返回值傳遞給eval()。 函數屬性func_*# 在Python 2裏,函數的裏的代碼能夠訪問到函數自己的特殊屬性。在Python 3裏,爲了一致性,這些特殊屬性被從新命名了。命令行
Notes Python 2 Python 3 ① a_function.func_name a_function.name ② a_function.func_doc a_function.doc ③ a_function.func_defaults a_function.defaults ④ a_function.func_dict a_function.dict ⑤ a_function.func_closure a_function.closure ⑥ a_function.func_globals a_function.globals ⑦ a_function.func_code a_function.code __name__屬性(原func_name)包含了函數的名字。 __doc__屬性(原funcdoc)包含了你在函數源代碼裏定義的文檔字符串(docstring) __defaults__屬性(原func_defaults)是一個保存參數默認值的元組。 __dict__屬性(原func_dict)是一個支持任意函數屬性的名字空間。 __closure__屬性(原func_closure)是一個由cell對象組成的元組,它包含了函數對自由變量(free variable)的綁定。 __globals__屬性(原func_globals)是一個對模塊全局名字空間的引用,函數自己在這個名字空間裏被定義。 __code__屬性(原func_code)是一個代碼對象,表示編譯後的函數體。 I/O方法xreadlines()# 在Python 2裏,文件對象有一個xreadlines()方法,它返回一個迭代器,一次讀取文件的一行。這在for循環中尤爲有用。事實上,後來的Python 2版本給文件對象自己添加了這樣的功能。code
在Python 3裏,xreadlines()方法再也不可用了。2to3能夠解決簡單的狀況,可是一些邊緣案例則須要人工介入。對象
Notes Python 2 Python 3 ① for line in a_file.xreadlines(): for line in a_file: ② for line in a_file.xreadlines(5): no change (broken) 若是你之前調用沒有參數的xreadlines(),2to3會把它轉換成文件對象自己。在Python 3裏,這種轉換後的代碼能夠完成前一樣的工做:一次讀取文件的一行,而後執行for循環的循環體。 若是你之前使用一個參數(每次讀取的行數)調用xreadlines(),2to3不能爲你完成從Python 2到Python 3的轉換,你的代碼會以這樣的方式失敗:AttributeError: '_io.TextIOWrapper' object has no attribute 'xreadlines'。你能夠手工的把xreadlines()改爲readlines()以使代碼能在Python 3下工做。(readline()方法在Python 3裏返回迭代器,因此它跟Python 2裏的xreadlines()效率是不相上下的。) ☃繼承
使用元組而非多個參數的lambda函數# 在Python 2裏,你能夠定義匿名lambda函數(anonymous lambda function),經過指定做爲參數的元組的元素個數,使這個函數實際上可以接收多個參數。事實上,Python 2的解釋器把這個元組「解開」(unpack)成命名參數(named arguments),而後你能夠在lambda函數裏引用它們(經過名字)。在Python 3裏,你仍然能夠傳遞一個元組做爲lambda函數的參數,可是Python解釋器不會把它解析成命名參數。你須要經過位置索引(positional index)來引用每一個參數。索引
Notes Python 2 Python 3 ① lambda (x,): x+ f(x) lambda x1: x1[0]+ f(x1[0]) ② lambda (x, y): x+ f(y) lambda x_y: x_y[0]+ f(x_y[1]) ③ 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] ④ lambda x, y, z: x+ y + z unchanged 若是你已經定義了一個lambda函數,它使用包含一個元素的元組做爲參數,在Python 3裏,它會被轉換成一個包含到x1[0]的引用的lambda函數。x1是2to3腳本基於原來元組裏的命名參數自動生成的。 使用含有兩個元素的元組(x, y)做爲參數的lambda函數被轉換爲x_y,它有兩個位置參數,即x_y[0]和x_y[1]。 2to3腳本甚至能夠處理使用嵌套命名參數的元組做爲參數的lambda函數。產生的結果代碼有點難以閱讀,可是它在Python 3下跟原來的代碼在Python 2下的效果是同樣的。 你能夠定義使用多個參數的lambda函數。若是沒有括號包圍在參數周圍,Python 2會把它看成一個包含多個參數的lambda函數;在這個lambda函數體裏,你經過名字引用這些參數,就像在其餘類型的函數裏所作的同樣。這種語法在Python 3裏仍然有效。 特殊的方法屬性# 在Python 2裏,類方法能夠訪問到定義他們的類對象(class object),也能訪問方法對象(method object)自己。im_self是類的實例對象;im_func是函數對象,im_class是類自己。在Python 3裏,這些屬性被從新命名,以遵循其餘屬性的命名約定。ip
Notes Python 2 Python 3 aClassInstance.aClassMethod.im_func aClassInstance.aClassMethod.func aClassInstance.aClassMethod.im_self aClassInstance.aClassMethod.self aClassInstance.aClassMethod.im_class aClassInstance.aClassMethod.self.class nonzero__特殊方法# 在Python 2裏,你能夠建立本身的類,並使他們可以在布爾上下文(boolean context)中使用。舉例來講,你能夠實例化這個類,並把這個實例對象用在一個if語句中。爲了實現這個目的,你定義一個特別的__nonzero()方法,它的返回值爲True或者False,當實例對象處在布爾上下文中的時候這個方法就會被調用 。在Python 3裏,你仍然能夠完成一樣的功能,可是這個特殊方法的名字變成了__bool__()。unicode
Notes Python 2 Python 3 ① class A: def nonzero(self): pass class A: def bool(self): pass ② class A: def nonzero(self, x, y): pass no change 當在布爾上下文使用一個類對象時,Python 3會調用__bool__(),而非__nonzero__()。 然而,若是你有定義了一個使用兩個參數的__nonzero__()方法,2to3腳本會假設你定義的這個方法有其餘用處,所以不會對代碼作修改。 八進制類型# 在Python 2和Python 3之間,定義八進制(octal)數的語法有輕微的改變。
Notes Python 2 Python 3 x =0755 x =0o755 sys.maxint# 因爲長整型和整型被整合在一塊兒了,sys.maxint常量再也不精確。可是由於這個值對於檢測特定平臺的能力仍是有用處的,因此它被Python 3保留,而且重命名爲sys.maxsize。
Notes Python 2 Python 3 ① from sys importmaxint from sys importmaxsize ② a_function(sys.maxint) a_function(sys.maxsize) maxint變成了maxsize。 全部的sys.maxint都變成了sys.maxsize。 全局函數callable()# 在Python 2裏,你可使用全局函數callable()來檢查一個對象是否可調用(callable,好比函數)。在Python 3裏,這個全局函數被取消了。爲了檢查一個對象是否可調用,能夠檢查特殊方法__call__()的存在性。
Notes Python 2 Python 3 callable(anything) hasattr(anything,'call') 全局函數zip()# 在Python 2裏,全局函數zip()可使用任意多個序列做爲參數,它返回一個由元組構成的列表。第一個元組包含了每一個序列的第一個元素;第二個元組包含了每一個序列的第二個元素;依次遞推下去。在Python 3裏,zip()返回一個迭代器,而非列表。
Notes Python 2 Python 3 ① zip(a, b, c) list(zip(a, b, c)) ② d.join(zip(a, b, c)) no change 最簡單的形式,你能夠經過調用list()函數包裝zip()的返回值來恢復zip()函數之前的功能,list()函數會遍歷這個zip()函數返回的迭代器,而後返回結果的列表表示。 在已經會遍歷序列全部元素的上下文環境裏(好比這裏對join()方法的調用),zip()返回的迭代器可以正常工做。2to3腳本會檢測到這些狀況,不會對你的代碼做出改變。 StandardError異常# 在Python 2裏,StandardError是除了StopIteration,GeneratorExit,KeyboardInterrupt,SystemExit以外全部其餘內置異常的基類。在Python 3裏,StandardError已經被取消了;使用Exception替代。
Notes Python 2 Python 3 x =StandardError() x =Exception() x =StandardError(a, b, c) x =Exception(a, b, c) types模塊中的常量# types模塊裏各類各樣的常量能幫助你決定一個對象的類型。在Python 2裏,它包含了表明全部基本數據類型的常量,如dict和int。在Python 3裏,這些常量被已經取消了。只須要使用基礎類型的名字來替代。
Notes Python 2 Python 3 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 ☞types.StringType被映射爲bytes,而非str,由於Python 2裏的「string」(非Unicode編碼的字符串,即普通字符串)事實上只是一些使用某種字符編碼的字節序列(a sequence of bytes)。 全局函數isinstance()# isinstance()函數檢查一個對象是不是一個特定類(class)或者類型(type)的實例。在Python 2裏,你能夠傳遞一個由類型(types)構成的元組給isinstance(),若是該對象是元組裏的任意一種類型,函數返回True。在Python 3裏,你依然能夠這樣作,可是不推薦使用把一種類型做爲參數傳遞兩次。
Notes Python 2 Python 3 isinstance(x,(int,float,int)) isinstance(x,(int,float)) basestring數據類型# Python 2有兩種字符串類型:Unicode編碼的字符串和非Unicode編碼的字符串。可是其實還有另外 一種類型,即basestring。它是一個抽象數據類型,是str和unicode類型的超類(superclass)。它不能被直接調用或者實例化,可是你能夠把它做爲isinstance()的參數來檢測一個對象是不是一個Unicode字符串或者非Unicode字符串。在Python 3裏,只有一種字符串類型,因此basestring就沒有必要再存在了。
Notes Python 2 Python 3 isinstance(x, basestring) isinstance(x, str) itertools模塊# Python 2.3引入了itertools模塊,它定義了全局函數zip(),map(),filter()的變體(variant),這些變體的返回類型爲迭代器,而非列表。在Python 3裏,因爲這些全局函數的返回類型原本就是迭代器,因此這些itertools裏的這些變體函數就被取消了。(在itertools模塊裏仍然還有許多其餘的有用的函數,而不只僅是以上列出的這些。)
Notes Python 2 Python 3 ① itertools.izip(a, b) zip(a, b) ② itertools.imap(a, b) map(a, b) ③ itertools.ifilter(a, b) filter(a, b) ④ from itertools import imap, izip, foo from itertools import foo 使用全局的zip()函數,而非itertools.izip()。 使用map()而非itertools.imap()。 itertools.ifilter()變成了filter()。 itertools模塊在Python 3裏仍然存在,它只是再也不包含那些已經轉移到全局名字空間的函數。2to3腳本可以足夠智能地去移除那些再也不有用的導入語句,同時保持其餘的導入語句的完整性。 sys.exc_type, sys.exc_value, sys.exc_traceback# 處理異常的時候,在sys模塊裏有三個你能夠訪問的變量:sys.exc_type,sys.exc_value,sys.exc_traceback。(實際上這些在Python 1的時代就有。)從Python 1.5開始,因爲新出的sys.exc_info,再也不推薦使用這三個變量了,這是一個包含全部以上三個元素的元組。在Python 3裏,這三個變量終於再也不存在了;這意味着,你必須使用sys.exc_info。
Notes Python 2 Python 3 sys.exc_type sys.exc_info()[0] sys.exc_value sys.exc_info()[1] sys.exc_traceback sys.exc_info()[2] 對元組的列表解析# 在Python 2裏,若是你須要編寫一個遍歷元組的列表解析,你不須要在元組值的周圍加上括號。在Python 3裏,這些括號是必需的。
Notes Python 2 Python 3 [i for iin 1,2] [i for iin (1,2)] os.getcwdu()函數# Python 2有一個叫作os.getcwd()的函數,它將當前的工做目錄做爲一個(非Unicode編碼的)字符串返回。因爲現代的文件系統可以處理能何字符編碼的目錄名,Python 2.3引入了os.getcwdu()函數。os.getcwdu()函數把當前工做目錄用Unicode編碼的字符串返回。在Python 3裏,因爲只有一種字符串類型(Unicode類型的),因此你只須要os.getcwd()就能夠了。
Notes Python 2 Python 3 os.getcwdu() os.getcwd() 元類(metaclass)# 在Python 2裏,你能夠經過在類的聲明中定義metaclass參數,或者定義一個特殊的類級別的(class-level)__metaclass__屬性,來建立元類。在Python 3裏,__metaclass__屬性已經被取消了。
Notes Python 2 Python 3 ① class C(metaclass=PapayaMeta): pass unchanged ② class Whip: metaclass = PapayaMeta class Whip(metaclass=PapayaMeta): pass ③ class C(Whipper, Beater): metaclass = PapayaMeta class C(Whipper, Beater, metaclass=PapayaMeta): pass 在聲明類的時候聲明metaclass參數,這在Python 2和Python 3裏都有效,它們是同樣的。 在類的定義裏聲明__metaclass__屬性在Python 2裏有效,可是在Python 3裏再也不有效。 2to3可以構建一個有效的類聲明,即便這個類繼承自多個父類。