Supporting Python 3(支持python3)——为Python 3做准备
2019獨(dú)角獸企業(yè)重金招聘Python工程師標(biāo)準(zhǔn)>>>
為Python3作準(zhǔn)備
在開始添加Python 3的支持前,為了能夠盡可能地順利過(guò)度到Python 3,你應(yīng)該通過(guò)修改對(duì)2to3來(lái)說(shuō)很難苦的東西來(lái)給你的代碼做一些準(zhǔn)備。即使你現(xiàn)在不打算遷移到Python 3,有一些事你也可以現(xiàn)在就做,這些事在一些情況下它們甚至?xí)涌炷愕拇a在Python 2下的運(yùn)行。
你可能想要讀在用現(xiàn)代的用句來(lái)改善你的代碼 上包含許多其他一些你能夠用到你的代碼中的改進(jìn)的章節(jié)。
在Python 2.7下運(yùn)行
這個(gè)過(guò)程的第一步是讓你的代碼在Python 2.6或者2.7下運(yùn)行。在這里你用的是什么版本不重要,但是明顯最后的Python 2是很有意義的,所以如果你能用Python 2.7的話,就用吧。
大多數(shù)代碼不用修改就可以直接運(yùn)行,但是從Python 2.5到2.6有幾個(gè)變化。在Python 2.6 as 和 with 是關(guān)鍵字,所以如果你使用這些作為變量就需要修改他們。最簡(jiǎn)單的辦法是在變量的尾部加上下劃線。
>>>?with_?=?True >>>?as_?=?False你還需要擺脫字符串異常。 使用字串符來(lái)拋出異常已經(jīng)不被推薦很長(zhǎng)時(shí)間了,主要是因?yàn)樗麄兎浅2混`活,例如你不能繼承他們。
>>>?raise?"Something?went?wrong!" Traceback?(most?recent?call?last): ... Something?went?wrong!在Python 3字符串異常已經(jīng)完全消失了。 在Python 2.6中你不能發(fā)出他們,但是為了向后兼容你還是可能捕捉到他們。在一些情況下你需要在你的代碼中移除所有字符串異常的使用并且在做任何事之前先讓他在Python 2.6下運(yùn)行。
>>>?raise?Exception("Something?went?wrong!") Traceback?(most?recent?call?last): ... Exception:?Something?went?wrong!下一步是在Python 2.6和Python 2.7下用 -3選項(xiàng)來(lái)運(yùn)行你的代碼。這個(gè)選項(xiàng)會(huì)對(duì)那個(gè)在Python 3中不支持及2to3不能轉(zhuǎn)換的部分發(fā)出警告。它主要針對(duì)的是那么已經(jīng)被棄用很久的和有新替代方式的部分,或者要被從標(biāo)準(zhǔn)庫(kù)中移除的模塊。例如對(duì)Classic Mac OS的支持已經(jīng)被移除了,現(xiàn)在只支持OS X并且因?yàn)檫@個(gè)原因?qū)lassic Mac OS特殊特性的支持模塊已經(jīng)被移除了。
你會(huì)得到一些下面列出的這么變化以及一些被重組庫(kù)的警告(但不是全部)。 庫(kù)的重組變化是很簡(jiǎn)單的,不需要解釋,警告會(huì)提醒你新模塊名字。
當(dāng)除以整數(shù)時(shí)用//代替/
是Python 2除兩個(gè)整數(shù)將反回兩個(gè)整數(shù)。那意味著5除以2將返回2。
>>>?5/2 2但是,在Python 3這會(huì)返回2.5。
>>>?5/2 2.5今天在Python 2中的除塵運(yùn)行符相信整除相除返回的是整數(shù)。但是使用2to3自動(dòng)轉(zhuǎn)換時(shí)會(huì)不知道操作數(shù)的類型是什么 ,因些它不知道除法操作是不是除以整數(shù)。 因此它不會(huì)在這里做任何轉(zhuǎn)換。這意味著如果你正在使用舊的整數(shù)除法操作,你的代碼在Python 3下會(huì)有很多錯(cuò)誤。
由于這個(gè)變化從Python 2.2就開始計(jì)劃了,Python 2.2及之后的版本都包含一個(gè)叫著浮點(diǎn)除法的使用兩個(gè)斜線的新操作。 即使有浮點(diǎn)數(shù),它也總是返回整數(shù)。任何你真的想要使用返回完整數(shù)字的浮點(diǎn)除法的地方,都應(yīng)該把除塵操作改成浮點(diǎn)除法操作。
>>>?5//2 2 >>>?5.0//2.0 2.0通常情況下,Python 2的除法操作是不必要的。解決這個(gè)問(wèn)題的最常見的方法是把其中一個(gè)整數(shù)轉(zhuǎn)換成浮點(diǎn)數(shù)或者在其中一個(gè)數(shù)字上添加一個(gè)小數(shù)點(diǎn)。
>>>?5/2.0 2.5 >>>?a?=?5 >>>?b?=?2 >>>?float(a)/b 2.5但是,有一個(gè)更合適的辦法,那就是允許使用Python 3的行為。這是通過(guò)從Python 2.2開始可能使用的__future__ import 做到的。
雖然把除號(hào)前的一個(gè)操作數(shù)中轉(zhuǎn)換成浮點(diǎn)數(shù)能很好地工作,但是在Python 3中不是沒(méi)有必要的并且使用__future__ import就可以避免它。
使用帶 -3 選項(xiàng)的Python 2.6運(yùn)行如果你用舊的整數(shù)除法的話就會(huì)提醒。
使用新式的類
在Python 2有兩種類,“舊式”和“新式”。“舊式”的類已經(jīng)在Python 3中移除了,因此即使沒(méi)有顯示地定義所有的類也都是object(對(duì)象)的子類。
在新舊的類上有一些不同,但是只有很少的情況下他們才會(huì)在Python 3下產(chǎn)生問(wèn)題。如果你使用了多重繼承可能會(huì)因?yàn)椴煌鉀Q順序遇到一些問(wèn)題。[4]
如果你用了多重繼承,因此你應(yīng)該在添加Python 3支持前切換成新式類。 通過(guò)確保所有的對(duì)象是object(對(duì)象)的子類來(lái)做到這個(gè)。并且你可能必須要在類定義中改變列出的超類順序。
單獨(dú)的二進(jìn)制數(shù)據(jù)和字符串
在Python 2,用str對(duì)象來(lái)保存二進(jìn)制數(shù)據(jù)和ASSCII文本,然而保存在unicode的文件數(shù)據(jù)比可以保存在ASCII的需要更多字符。在Python 3,取代str和unicode對(duì)象的是你可以用bytes對(duì)象保存二進(jìn)制數(shù)據(jù)并且使用str對(duì)象保存不管是不是Unicode的所有類型文本數(shù)據(jù)。即使有明顯的差異,Python 3的str類型或多或少類似于Python 2的unicode類型,而bytes類型頗為類似Python 2的str類型。
為這個(gè)作準(zhǔn)備的第一步是確保沒(méi)有在二進(jìn)制和文本數(shù)據(jù)上使用相同的變量名。在Python 2這不會(huì)給你帶來(lái)麻煩,但是在Python 3會(huì)的,因此盡可能保證二進(jìn)制數(shù)據(jù)和文本是分開的。
在Python 2上,“t”和“b”文件模式標(biāo)識(shí)志可以改變?cè)谝恍┢脚_(tái)(例如Windows)上換行是如何處理的。但是這些標(biāo)志在Unix上不會(huì)產(chǎn)生不同作用,因此為Unix開發(fā)的很多項(xiàng)目往往會(huì)乎略那些標(biāo)志并且在文本模式打開二進(jìn)制文件。然而在Python 3 這些標(biāo)志也決定了當(dāng)你從文件中讀數(shù)據(jù)返回的結(jié)果是bytes對(duì)象還是unicode對(duì)象。雖然文本標(biāo)志是默認(rèn)的,但是一定要添加上它,因?yàn)槟潜硎颈疚哪J绞怯心康牡牟⒉恢皇悄阃浖訕?biāo)志。
帶上-3選項(xiàng)執(zhí)行Python 2.6是不會(huì)提醒這個(gè)問(wèn)題的,因?yàn)镻ython 2根本沒(méi)有辦法知道數(shù)據(jù)是文本還是二進(jìn)制數(shù)據(jù)。
當(dāng)排序時(shí),使用key來(lái)代替cmp
在Python 2帶排序方法可以帶一個(gè)cmp參數(shù),這個(gè)參數(shù)是一個(gè)比較兩個(gè)值并返回-1,0或者1的函數(shù)。
>>>?def?compare(a,?b): ...?????"""Comparison?that?ignores?the?first?letter""" ...?????return?cmp(a[1:],?b[1:]) >>>?names?=?['Adam',?'Donald',?'John'] >>>?names.sort(cmp=compare) >>>?names ['Adam',?'John',?'Donald']從Python 2.4開,.sort()和新的sorted()函數(shù)一樣(見使用sorted()代替.sort()),sorted()可以帶一個(gè)返回排序鍵值的函數(shù)作為key參數(shù)。
>>>?def?keyfunction(item): ...?????"""Key?for?comparison?that?ignores?the?first?letter""" ...?????return?item[1:] >>>?names?=?['Adam',?'Donald',?'John'] >>>?names.sort(key=keyfunction) >>>?names ['Adam',?'John',?'Donald']這使用真情更容易并且執(zhí)行起來(lái)更快。當(dāng)使用cmp參數(shù)時(shí),排序比較每一對(duì)值,因此對(duì)每個(gè)項(xiàng)目都要多次調(diào)用比較函數(shù)。一個(gè)更大的數(shù)據(jù)集合將要為每一個(gè)項(xiàng)目調(diào)用更多次的比較函數(shù)。使用key函數(shù),排序使用保存每一個(gè)項(xiàng)目的鍵值并比較他們來(lái)取代,因些每一個(gè)項(xiàng)目只調(diào)用一次key函數(shù)。因?yàn)檫@個(gè)原因比較大數(shù)據(jù)集合時(shí)會(huì)快很多。
key函數(shù)往往可以用如此簡(jiǎn)單地用lambda來(lái)替代:
>>>?names?=?['Adam',?'Donald',?'John'] >>>?names.sort(key=lambda?x:?x[1:]) >>>?names ['Adam',?'John',?'Donald']Python?2.4 還引入了reverse參數(shù)。
>>>?names?=?['Adam',?'Donald',?'John'] >>>?names.sort(key=lambda?x:?x[1:],?reverse=True) >>>?names ['Donald',?'John',?'Adam']在你排序的是幾個(gè)值時(shí),使用key跟使用cmp相較起來(lái)差距不是很明顯。比方說(shuō),我們想要首先按名字的長(zhǎng)度排序并且相同長(zhǎng)度的按字母排序。 用key函數(shù)做這個(gè)并不顯而易見,但是解決方法通常先按次要求排序之后再按另一個(gè)要求排序。
>>>?names?=?['Adam',?'Donald',?'John'] >>>?#?Alphabetical?sort >>>?names.sort() >>>?#?Long?names?should?go?first >>>?names.sort(key=lambda?x:?len(x),?reverse=True) >>>?names ['Donald',?'Adam',?'John']這個(gè)可以工作是因?yàn)閺腜ython 2.3開始采用了timsort排序算法[1]。這是一個(gè)平穩(wěn)的算法,這意味著如果比較的兩個(gè)項(xiàng)目是相同的它將會(huì)保留他們?cè)瓉?lái)的順序。
你也可以寫一個(gè)能返回結(jié)合了兩個(gè)鍵值的值的key函數(shù)并且一氣呵成地完成排序。令人驚奇的是這不一定會(huì)更快,你需要測(cè)試下哪一個(gè)解決方案在你的情況下會(huì)更快,這取決于數(shù)據(jù)和key函數(shù)。
>>>?def?keyfunction(item): ...?????"""Sorting?on?descending?length?and?alphabetically""" ...?????return?-len(item),?item >>>?names?=?['Adam',?'Donald',?'John'] >>>?names.sort(key=keyfunction) >>>?names ['Donald',?'Adam',?'John']key參數(shù)在Python 2.4引入的,所以如果你想要支持Python 2.3就不能用它了。如果你想要用key函數(shù)做很多的排序,最好的辦法是為Python 2.3實(shí)現(xiàn)一個(gè)簡(jiǎn)單的在Python 2.4及之后版本的sorted()函數(shù)并且用那個(gè)來(lái)替代內(nèi)置的sorted()。
>>>?import?sys >>>?if?sys.version_info?<?(2,?4): ...????def?sorted(data,?key): ...????????mapping?=?{} ...????????for?x?in?data: ...????????????mapping[key(x)]?=?x ...????????keys?=?mapping.keys() ...????????keys.sort() ...????????return?[mapping[x]?for?x?in?keys] >>>?data?=?['ant',?'Aardvark',?'banana',?'Dingo'] >>>?sorted(data,?key=str.lower) ['Aardvark',?'ant',?'banana',?'Dingo']Python 2.4現(xiàn)在已經(jīng)有5年那么老了,所以你不太可能需要支持Python 2.3。
警告
使用-3選項(xiàng)運(yùn)行Python只會(huì)在你顯示地使用cmp參數(shù)時(shí)警告你:
>>>?l.sort(cmp=cmpfunction) __main__:1:?DeprecationWarning:?the?cmp?argument?is?not supported?in?3.x但是如果像下面這樣使用將不警告:
>>>?l.sort(cmpfunction)?所以這個(gè)語(yǔ)法可能會(huì)漏網(wǎng)之魚。在Python 3運(yùn)行這些代碼時(shí),在這些情況下你會(huì)得到一個(gè)TypeError: mustuse keyword argument for key function 。
在Python 2.7和Python 3.2及后面的版本有一個(gè)函數(shù)可以通過(guò)一個(gè)包裝類把比較函數(shù)轉(zhuǎn)換成key函數(shù)。它是很聰明的,但反而會(huì)讓比較函數(shù)更慢,因此這只是最后的手段。
>>>?from?functools?import?cmp_to_key >>>?def?compare(a,?b):?return?cmp(a[1:],?b[1:]) >>>?sorted(['Adam',?'Donald',?'John'],?key=cmp_to_key(compare)) ['Adam',?'John',?'Donald']使用豐富的比較運(yùn)算符
在Python 2最常見的支持對(duì)象比較和排序的方式是實(shí)現(xiàn)一個(gè)使用內(nèi)置cmp()函數(shù)的__cmp__()方法,像這樣類就可以根據(jù)姓氏排序了:
>>>?class?Orderable(object): ... ...?????def?__init__(self,?firstname,?lastname): ...?????????self.first?=?firstname ...?????????self.last?=?lastname ... ...?????def?__cmp__(self,?other): ...?????????return?cmp("%s,?%s"?%?(self.last,?self.first), ...????????????????????"%s,?%s"?%?(other.last,?other.first)) ... ...?????def?__repr__(self): ...?????????return?"%s?%s"?%?(self.first,?self.last) ... >>>?sorted([Orderable('Donald',?'Duck'), ...?????????Orderable('Paul',?'Anka')]) [Paul?Anka,?Donald?Duck]然則,你可以擁有類似colors這樣的即不能比較大小但可以比較是否相等的類,因此從Python 2.1開始也支持一個(gè)比較操作符對(duì)應(yīng)一個(gè)方法的豐富的比較方法。他們是 __lt__ 對(duì)應(yīng) <,__le__ 對(duì)應(yīng)<=, __eq__ 對(duì)應(yīng)==, __ne__ 對(duì)應(yīng)!=, __gt__對(duì)應(yīng)> ,以及 __ge__ 對(duì)應(yīng) >=。
同時(shí)擁有豐富的比較方法和__cmp__()方法違反了只有一種方式來(lái)實(shí)現(xiàn)比較的原則,所以在Python 3對(duì)__cmp__()的支持已經(jīng)被移除了。因此對(duì)Python 3,如果你的類需要被比較的話,你必須要所有的豐富比較操作符。 沒(méi)有必要在開始支持Python 3做這個(gè),但做這些是一種體驗(yàn)。
相對(duì)棘手的
寫比較方法會(huì)相當(dāng)棘手,因?yàn)槟憧赡苄枰幚聿煌愋偷谋容^。如果比較函數(shù)不知道如何與其他對(duì)象比較時(shí)會(huì)返回NotImplemented常量。返回的NotImplemented 可以作為一個(gè)Python的比較標(biāo)志來(lái)讓Python償試反向比較。所以如果你的__lt__()方法返回NotImplemented那么Python會(huì)償試用調(diào)用其他類的__gt__()方法來(lái)代替。
注意
這意味著你永遠(yuǎn)都不應(yīng)該在你的豐富比較方法中調(diào)用其他類的比較操作!你會(huì)找到幾個(gè)轉(zhuǎn)換大于(就像self.__gt__(other))成返回other < self的豐富比較助手的例子。但是你調(diào)用other.__lt__(self)卻會(huì)返回NotImplemented而不是再次償試self.__gt__(other)并且無(wú)限遞歸。
一旦你理解了所有案例,實(shí)現(xiàn)一個(gè)好的正解運(yùn)行的豐富比較操作集不會(huì)困難,但是掌握那些卻不是完全不重要。你可以用許多不同的方式做它,我的首選方式是這樣混合,這樣就可以同時(shí)在Python 2和Python 3很好地工作。
class?ComparableMixin(object):def?_compare(self,?other,?method):try:return?method(self._cmpkey(),?other._cmpkey())except?(AttributeError,?TypeError):#?_cmpkey?not?implemented,?or?return?different?type,#?so?I?can't?compare?with?"other".return?NotImplementeddef?__lt__(self,?other):return?self._compare(other,?lambda?s,?o:?s?<?o)def?__le__(self,?other):return?self._compare(other,?lambda?s,?o:?s?<=?o)def?__eq__(self,?other):return?self._compare(other,?lambda?s,?o:?s?==?o)def?__ge__(self,?other):return?self._compare(other,?lambda?s,?o:?s?>=?o)def?__gt__(self,?other):return?self._compare(other,?lambda?s,?o:?s?>?o)def?__ne__(self,?other):return?self._compare(other,?lambda?s,?o:?s?!=?o)前面提到的Ptyhon 3.2的functools.total_ordering()類裝飾器也是一個(gè)很好的解決辦法,并且它同樣可以用復(fù)制并用在其它版本上。但是因?yàn)樗玫念愌b飾器,所以不能在Python 2.6以下版本使用。
使用前面的混合,你需要實(shí)現(xiàn)返回能一反被比較的對(duì)象鍵值的_cmpkey()方法,類似于比較時(shí)用的key()函數(shù)。實(shí)現(xiàn)真情可以類似這樣:
>>>?from?mixin?import?ComparableMixin >>>?class?Orderable(ComparableMixin): ... ...?????def?__init__(self,?firstname,?lastname): ...?????????self.first?=?firstname ...?????????self.last?=?lastname ... ...?????def?_cmpkey(self): ...?????????return?(self.last,?self.first) ... ...?????def?__repr__(self): ...?????????return?"%s?%s"?%?(self.first,?self.last) ...>>>?sorted([Orderable('Donald',?'Duck'), ...?????????Orderable('Paul',?'Anka')]) [Paul?Anka,?Donald?Duck]如果對(duì)象比較時(shí)沒(méi)有實(shí)現(xiàn) _cmpkey()方法或者前面的混合使用self._cmpkey()的返回值返回的值不能被比較,前面的混合將會(huì)返回NotImplemented。 這意味著每一個(gè)對(duì)象都要有一個(gè)能返回能合其他有能返回一個(gè)元組的_cmpkey()的對(duì)象比較的_cmpkey()。以及最重要的是如它不能被比較,如果其他對(duì)象如何去比較兩個(gè)對(duì)象,運(yùn)算符會(huì)備用地尋問(wèn)其他對(duì)象。這樣你就擁有了一個(gè)有最大機(jī)會(huì)進(jìn)行有意義比較的對(duì)象。
實(shí)現(xiàn) __hash__()
在Python 2,如果你想實(shí)現(xiàn) __eq__() 你也需要重寫__hash__()。這是因?yàn)閮蓚€(gè)對(duì)象比較趕快相等也需要相同的哈希值。 如果對(duì)象是可變的,你必須要把設(shè)置__hash__成None來(lái)把它標(biāo)定成可變的。這意味著你不能把它用作字典的鍵值, 這很好,只有不可變對(duì)象可以做字典鍵。
在Python 3,如果你定義了__eq__(), __hash__ 會(huì)被自動(dòng)設(shè)置成, 并且對(duì)象變成不能被哈希。所以對(duì)于Python 3,除非是一個(gè)不變的對(duì)象或者你想把它作為一個(gè)鍵值,你都不需要重寫__hash__()。
被__hash__()返回的值需要是一個(gè)整數(shù),兩個(gè)比較相等的對(duì)象一定有相同的哈希值。它必須在對(duì)象的整個(gè)存活期內(nèi)保持不變,這也是為什么可變對(duì)象為什么必須設(shè)置__hash__ = None來(lái)標(biāo)記它們是不能哈希的。
如果你使用前面提及的實(shí)現(xiàn)比較運(yùn)算符的_cmpkey()方法,那么不實(shí)現(xiàn)__hash__()是很容易的:
>>>?from?mixin?import?ComparableMixin >>>?class?Hashable(ComparableMixin): ...?????def?__init__(self,?firstname,?lastname): ...?????????self._first?=?firstname ...?????????self._last?=?lastname ... ...?????def?_cmpkey(self): ...?????????return?(self._last,?self._first) ... ...?????def?__repr__(self): ...?????????return?"%s(%r,?%r)"?%?(self.__class__.__name__, ...????????????????????????????????self._first,?self._last) ... ...?????def?__hash__(self): ...?????????return?hash(self._cmpkey()) ... >>>?d?=?{Hashable('Donald',?'Duck'):?'Daisy?Duck'} >>>?d {Hashable('Donald',?'Duck'):?'Daisy?Duck'}這個(gè)類屬性按照慣例使用前導(dǎo)的下劃線來(lái)標(biāo)記成內(nèi)部使用,但他們不是傳統(tǒng)意義上的不可變。如果你想要一個(gè)在Python中真正的不可變類,最簡(jiǎn)單的辦法就是繼承collections.namedtuple,但那超出了本書的范疇。
確保你沒(méi)有用任何一個(gè)被移除的模塊
很多在標(biāo)準(zhǔn)庫(kù)中的模塊在Python 3中已經(jīng)被丟棄了。他們中的多大數(shù)是對(duì)不提供被新模塊支持的更好接口的舊系統(tǒng)的特別支持。
如果你使用了一些更常用的模塊,使用-3選項(xiàng)運(yùn)行Python 2.6 將會(huì)警告你。你使用了那些Python 2.6不會(huì)發(fā)出警告的模塊是相當(dāng)不可能的,但是如果你正在或者計(jì)劃同時(shí)支持Python 2和Python 3,如果有話你必須要盡可能替換成現(xiàn)在對(duì)應(yīng)的。
在 被移除的模塊 上有一個(gè)被移除模塊的列表。
測(cè)試覆蓋率和tox
有一個(gè)好的測(cè)試集對(duì)任何項(xiàng)目都是有價(jià)值的。當(dāng)你添加Python 3支持時(shí),測(cè)試可以把這個(gè)過(guò)程加快很多,因?yàn)槟阈枰槐橛忠槐榈貓?zhí)行測(cè)試而手工測(cè)試要花掉大量時(shí)間。
用更多的測(cè)試來(lái)提高測(cè)試覆蓋率總是一個(gè)好主意。最流行的獲得你的模塊的測(cè)試覆蓋率的Python 工具是Ned Batchelder的coverage 模塊。[2] 許多像zope.testing、nose及py.test這樣的測(cè)試運(yùn)行框架都包含對(duì)coverage模塊的支持,所以你可能已經(jīng)安裝了。
如果你在開發(fā)一個(gè)支持所有版本Python的模塊,為所有這些版本執(zhí)行測(cè)試迅速會(huì)變成一個(gè)令人厭煩的工作。為了解決這個(gè)Holger Krekel制作了一個(gè)叫做tox[3]的工具,這個(gè)工具會(huì)為每一個(gè)你想要支持的版本安裝虛擬環(huán)境并且使用一個(gè)簡(jiǎn)單的命令對(duì)所有這些版本執(zhí)行你的測(cè)試。它似乎是一件小事,它是的,但是它會(huì)增加一點(diǎn)點(diǎn)更愉快的體驗(yàn)。如果你計(jì)劃同時(shí)支持Python 2和Python 3,你應(yīng)該試試看。
可選:在字典中使用迭代器方法(iterator-methods)
從Python 2.2開始內(nèi)置的字典類型有iterkeys()、 itervalues() 、 iteritems() 方法。他們產(chǎn)生的數(shù)據(jù)像是keys()、values() 和items()產(chǎn)生的,但他們返回的不是列表而是迭代器(iterator),在使用巨大的字典時(shí)這可以節(jié)省時(shí)間和內(nèi)存。
>>>?dict?=?{'Adam':?'Eve',?'John':?'Yoko',?'Donald':?'Daisy'} >>>?dict.keys() ['Donald',?'John',?'Adam']>>>?dict.iterkeys()? <dictionary-keyiterator?object?at?0x...>在Python 3標(biāo)準(zhǔn)的keys(),、values() 和 items()返回和迭代器非常類似的字典視圖。因?yàn)椴痪弥笤谶@些方法中的迭代器變量要被移除。
2to3 會(huì)把迭代器方法的使用轉(zhuǎn)換成標(biāo)準(zhǔn)方法。通過(guò)明確地使用迭代器方法,你表明不需要一個(gè)列表,這對(duì)2to3的轉(zhuǎn)換是有幫助的,否則為了安全要用alist(dict.values())來(lái)取代dict.values()調(diào)用。
Python 2.7也有像.viewitems()、.viewkeys() 和 .viewvalues()這樣可用的新視圖迭代器,但因?yàn)樗麄冊(cè)诟绲腜ython版本中不存在所以他們只有在你打算放棄Python 2.6及更早的版本時(shí)才有用。
還要注意的是如果你的代碼依靠返回的列表,那么你可能誤用未知的字典。例如:下面的代碼,你事實(shí)上不能確定每次的鍵的順序是相同的,因?yàn)檫@個(gè)原因你可能無(wú)法預(yù)測(cè)該代碼的行為。這在調(diào)試時(shí)會(huì)帶來(lái)一些麻煩。
>>>?dict?=?{'Adam':?'Eve',?'John':?'Yoko',?'Donald':?'Daisy'} >>>?dict.keys() [0]'Donald'記住,如果你想要遍歷字典就使用for x in dict,這樣在Python 2和Python 3中都會(huì)自動(dòng)使用迭代器。
>>>?dict?=?{'Adam':?'Eve',?'John':?'Yoko',?'Donald':?'Daisy'} >>>?for?x?in?dict: ...?????print?'%s?+?%s?==?True'?%?(x,?dict[x]) Donald?+?Daisy?==?True John?+?Yoko?==?True Adam?+?Eve?==?True附注
| [1] | http://en.wikipedia.org/wiki/Timsort |
| [2] | https://pypi.python.org/pypi/coverage |
| [3] | http://testrun.org/tox/latest/ |
| [4] | 見 http://www.python.org/download/releases/2.2.3/descrintro/#mro |
在湖聞?wù)磷?#xff1a;
原文http://python3porting.com/preparing.html
引導(dǎo)頁(yè)Supporting Python?3:(支持Python3):深入指南
目錄Supporting Python?3(支持Python 3)——目錄
轉(zhuǎn)載于:https://my.oschina.net/soarwilldo/blog/506415
總結(jié)
以上是生活随笔為你收集整理的Supporting Python 3(支持python3)——为Python 3做准备的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: HTML特殊字符大全2
- 下一篇: 迷你世界万能土块怎么弄