更新時間:2018-10-31 來源:黑馬程序員 瀏覽量:
許多 Python 初學者想知道他們應該從 Python 的哪個版本開始學習。對于這個問題我的答案是 “你學習你喜歡的教程的版本,然后檢查他們之間的不同。"
但是如果你開始一個新項目,并且有選擇權?我想說的是目前沒有對錯,只要你計劃使用的庫 Python 2.7.x 和 Python 3.x 雙方都支持的話。盡管如此,當在編寫它們中的任何一個的代碼,或者是你計劃移植你的項目的時候,是非常值得看看這兩個主要流行的 Python 版本之間的差別的,以便避免常見的陷阱。
future模塊
Python 3.x 介紹的 一些Python 2 不兼容的關鍵字和特性可以通過在 Python 2 的內置__future__模塊導入。如果你計劃讓你的代碼支持 Python 3.x,建議你使用__future__模塊導入。例如,如果我想要 在Python 2 中表現(xiàn) Python 3.x 中的整除,我們可以通過如下導入
from__future__importdivision
更多的__future__模塊可被導入的特性被列在下表中:
featureoptional inmandatory ineffect
nested_scopes2.1.0b12.2PEP 227: Statically Nested Scopes
generators2.2.0a12.3PEP 255: Simple Generators
division2.2.0a23.0PEP 238: Changing the Division Operator
absolute_import2.5.0a13.0PEP 328: Imports: Multi-Line and Absolute/Relative
with_statement2.5.0a12.6PEP 343: The “with” Statement
print_function2.6.0a23.0PEP 3105: Make print a function
unicode_literals2.6.0a23.0PEP 3112: Bytes literals in Python 3000
(Source:https://docs.python.org/2/library/future.html)
fromplatformimportpython_version
print函數(shù)
很瑣碎,而print語法的變化可能是最廣為人知的了,但是仍值得一提的是: Python 2 的print聲明已經(jīng)被print()函數(shù)取代了,這意味著我們必須包裝我們想打印在小括號中的對象。
Python 2 不具有額外的小括號問題。但對比一下,如果我們按照 Python 2 的方式不使用小括號調用print函數(shù),Python 3 將拋出一個語法異常(SyntaxError)。
Python 2
print'Python', python_version()print'Hello, World!'print('Hello, World!')print"text", ;print'print more text on the same line'
Python2.7.6Hello, World!Hello, World!textprintmore textonthe same line
Python 3
print('Python', python_version())print('Hello, World!')print("some text,", end="")print(' print more text on the same line')
Python3.4.1Hello, World!some text,printmore textonthe same line
print'Hello, World!'
File"", line1print'Hello, World!'^SyntaxError: invalid syntax
注意
以上通過 Python 2 使用Printing "Hello, World"是非常正常的,盡管如此,如果你有多個對象在小括號中,我們將創(chuàng)建一個元組,因為print在 Python 2 中是一個聲明,而不是一個函數(shù)調用。
print'Python', python_version()print('a','b')print'a','b'
Python2.7.7('a','b')a b
xrange
在 Python 2 中xrange()創(chuàng)建迭代對象的用法是非常流行的。比如: for 循環(huán)或者是列表/集合/字典推導式。
這個表現(xiàn)十分像生成器(比如?!岸栊郧笾怠?。但是這個xrange-iterable是無窮的,意味著你可以無限遍歷。
由于它的惰性求值,如果你不得僅僅不遍歷它一次,xrange()函數(shù) 比range()更快(比如 for 循環(huán))。盡管如此,對比迭代一次,不建議你重復迭代多次,因為生成器每次都從頭開始。
在 Python 3 中,range()是像xrange()那樣實現(xiàn)以至于一個專門的xrange()函數(shù)都不再存在(在 Python 3 中xrange()會拋出命名異常)。
importtimeitn =10000deftest_range(n):returnforiinrange(n):passdeftest_xrange(n):foriinxrange(n):pass
Python 2
print'Python', python_version()print'\ntiming range()'%timeit test_range(n)print'\n\ntiming xrange()'%timeit test_xrange(n)Python2.7.6timing range()1000loops, bestof3:433μs perlooptiming xrange()1000loops, bestof3:350μs perloop
Python 3
print('Python', python_version())print('\ntiming range()')%timeit test_range(n)Python3.4.1timing range()1000loops, bestof3:520μs perloop
print(xrange(10))---------------------------------------------------------------------------NameError Traceback (most recentcalllast)in()----> 1 print(xrange(10))NameError: name'xrange'isnotdefined
Python 3 中的range對象的__contains__方法
另外一件值得一提的事情就是在 Python 3 中range有一個新的__contains__方法(感謝Yuchen Ying指出了這個),__contains__方法可以加速"查找"在 Python 3.x 中顯著的整數(shù)和布爾類型。
x =10000000defval_in_range(x, val):returnvalinrange(x)defval_in_xrange(x, val):returnvalinxrange(x)print('Python', python_version())assert(val_in_range(x, x/2) ==True)assert(val_in_range(x, x//2) ==True)%timeit val_in_range(x, x/2)%timeit val_in_range(x, x//2)Python3.4.11loops, best of3:742ms per loop1000000loops, best of3:1.19μs per loop
基于以上的timeit的結果,當它使一個整數(shù)類型,而不是浮點類型的時候,你可以看到執(zhí)行查找的速度是 60000 倍快。盡管如此,因為 Python 2.x 的range或者是xrange沒有一個__contains__方法,這個整數(shù)類型或者是浮點類型的查詢速度不會相差太大。
print'Python', python_version()assert(val_in_xrange(x, x/2.0) == True)assert(val_in_xrange(x, x/2) == True)assert(val_in_range(x, x/2) == True)assert(val_in_range(x, x//2) == True)%timeit val_in_xrange(x, x/2.0)%timeit val_in_xrange(x, x/2)%timeit val_in_range(x, x/2.0)%timeit val_in_range(x, x/2)Python2.7.71loops, bestof3:285ms perloop1loops, bestof3:179ms perloop1loops, bestof3:658ms perloop1loops, bestof3:556ms perloop
下面說下__contain__方法并沒有加入到 Python 2.x 中的證據(jù):
print('Python', python_version())range.__contains__Python3.4.1
print 'Python', python_version()range.__contains__Python 2.7.7---------------------------------------------------------------------------AttributeError Traceback (most recentcalllast)in()1print'Python', python_version()----> 2 range.__contains__AttributeError:'builtin_function_or_method'object hasnoattribute'__contains__'
print 'Python', python_version()xrange.__contains__Python 2.7.7---------------------------------------------------------------------------AttributeError Traceback (most recentcalllast)in()1print'Python', python_version()----> 2 xrange.__contains__AttributeError: type object'xrange'hasnoattribute'__contains__'
**注意在 Python 2 和 Python 3 中速度的不同***
有些猿類指出了 Python 3 的range()和 Python 2 的xrange()之間的速度不同。因為他們是用相同的方法實現(xiàn)的,因此期望相同的速度。盡管如此,這事實在于 Python 3 傾向于比 Python 2 運行的慢一點。
deftest_while():i =0whilei <20000: i +=1return
print('Python', python_version())%timeit test_while()Python3.4.1100loops, bestof3:2.68ms perloop
print'Python', python_version()%timeit test_while()Python2.7.61000loops, bestof3:1.72ms perloop