1.Python入門之--Python 2.7.x 和 Python 3.x 的主要區別

注:本文的原文地址為

http://segmentfault.com/a/1190000000618286

許多 Python 初學者想知道他們應該從 Python 的哪個版本開始學習。對于這個問題我的答案是 “你學習你喜歡的教程的版本,然后檢查他們之間的不同。"

但是如果你開始一個新項目,并且有選擇權?我想說的是目前沒有對錯,只要你計劃使用的庫 Python 2.7.x 和 Python 3.x 雙方都支持的話。盡管如此,當在編寫它們中的任何一個的代碼,或者是你計劃移植你的項目的時候,是非常值得看看這兩個主要流行的 Python 版本之間的差別的,以便避免常見的陷阱,

章節

使用__future__模塊

print函數

Integer division

Unicode

xrange

Raising exceptions

Handling exceptions

next()函數 和.next()方法

For 循環變量和全局命名空間泄漏

比較不可排序類型

通過input()解析用戶的輸入

返回可迭代對象,而不是列表

更多的關于 Python 2 和 Python 3 的文章

future模塊

Python 3.x 介紹的 一些Python 2 不兼容的關鍵字和特性可以通過在 Python 2 的內置__future__模塊導入。如果你計劃讓你的代碼支持 Python 3.x,建議你使用__future__模塊導入。例如,如果我想要 在Python 2 中表現 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函數

[跳轉到章節預覽]

很瑣碎,而print語法的變化可能是最廣為人知的了,但是仍值得一提的是: Python 2 的print聲明已經被print()函數取代了,這意味著我們必須包裝我們想打印在小括號中的對象。

Python 2 不具有額外的小括號問題。但對比一下,如果我們按照 Python 2 的方式不使用小括號調用print函數,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"是非常正常的,盡管如此,如果你有多個對象在小括號中,我們將創建一個元組,因為print在 Python 2 中是一個聲明,而不是一個函數調用。

print'Python', python_version()print('a','b')print'a','b'

Python2.7.7('a','b')a b

整除

[跳轉到章節預覽]

如果你正在移植代碼,這個變化是特別危險的。或者你在 Python 2 上執行 Python 3 的代碼。因為這個整除的變化表現在它會被忽視(即它不會拋出語法異常)。

因此,我還是傾向于使用一個float(3)/2或3/2.0代替在我的 Python 3 腳本保存在 Python 2 中的3/2的一些麻煩(并且反而過來也一樣,我建議在你的 Python 2 腳本中使用from __future__ import division)

Python 2

print'Python', python_version()print'3 / 2 =',3/2print'3 // 2 =',3// 2print'3 / 2.0 =',3/2.0print'3 // 2.0 =',3// 2.0

Python2.7.63/2=13// 2 = 13/2.0=1.53// 2.0 = 1.0

Python 3

print('Python', python_version())print('3 / 2 =',3/2)print('3 // 2 =',3// 2)print('3 / 2.0 =',3/2.0)print('3 // 2.0 =',3// 2.0)

Python3.4.13/2=1.53// 2 = 13/2.0=1.53// 2.0 = 1.0

Unicode

[跳轉到章節預覽]

Python 2 有ASCII str()類型,unicode()是單獨的,不是 byte 類型。

現在, 在 Python 3,我們最終有了Unicode (utf-8)字符串,以及一個字節類:byte和bytearrays。

Python 2

print'Python', python_version()

Python2.7.6

printtype(unicode('this is like a python3 str type'))

printtype(b'byte type does not exist')

print'they are really'+ b' the same'they are really the same

printtype(bytearray(b'bytearray oddly does exist though'))

Python 3

print('Python', python_version())print('strings are now utf-8 \u03BCnico\u0394é!')Python3.4.1strings are now utf-8μnicoΔé!

print('Python', python_version(), end="")print(' has', type(b' bytes for storing data'))Python3.4.1has

print('and Python', python_version(), end="")print(' also has', type(bytearray(b'bytearrays')))andPython3.4.1also has

'note that we cannot add a string' + b'bytes for data'---------------------------------------------------------------------------TypeError? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Traceback (most recentcalllast)in()----> 1 'note that we cannot add a string' + b'bytes for data'TypeError: Can't convert 'bytes' object to str implicitly

xrange

[跳轉到章節預覽]

在 Python 2 中xrange()創建迭代對象的用法是非常流行的。比如: for 循環或者是列表/集合/字典推導式。

這個表現十分像生成器(比如。“惰性求值”)。但是這個xrange-iterable是無窮的,意味著你可以無限遍歷。

由于它的惰性求值,如果你不得僅僅不遍歷它一次,xrange()函數 比range()更快(比如 for 循環)。盡管如此,對比迭代一次,不建議你重復迭代多次,因為生成器每次都從頭開始。

在 Python 3 中,range()是像xrange()那樣實現以至于一個專門的xrange()函數都不再存在(在 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 中顯著的整數和布爾類型。

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的結果,當它使一個整數類型,而不是浮點類型的時候,你可以看到執行查找的速度是 60000 倍快。盡管如此,因為 Python 2.x 的range或者是xrange沒有一個__contains__方法,這個整數類型或者是浮點類型的查詢速度不會相差太大。

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 中的證據:

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()之間的速度不同。因為他們是用相同的方法實現的,因此期望相同的速度。盡管如此,這事實在于 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

Raising exceptions

[跳轉到章節預覽]

Python 2 接受新舊兩種語法標記,在 Python 3 中如果我不用小括號把異常參數括起來就會阻塞(并且反過來引發一個語法異常)。

Python 2

print'Python', python_version()Python2.7.6

raise IOError, "file error"---------------------------------------------------------------------------IOError? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Traceback (most recentcalllast)in()----> 1 raise IOError, "file error"IOError: file error

raise IOError("file error")---------------------------------------------------------------------------IOError? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Traceback (most recentcalllast)in()----> 1 raise IOError("file error")IOError: file error

Python 3

print('Python', python_version())Python3.4.1

raiseIOError,"file error"

File"", line1raiseIOError,"file error"^SyntaxError: invalid syntaxThe proper way toraisean exceptioninPython3:

print('Python', python_version())raise IOError("file error")Python3.4.1---------------------------------------------------------------------------OSError? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Traceback (most recent call last)in()1print('Python', python_version())---->2raise IOError("file error")OSError: file error

Handling exceptions

在 Python 3 中處理異常也輕微的改變了,在 Python 3 中我們現在使用as作為關鍵詞。

python 2

print'Python', python_version()try:? ? let_us_cause_a_NameErrorexcept NameError, err:printerr,'--> our error message'Python2.7.6name'let_us_cause_a_NameError'isnotdefined-->ourerror message

Python 3

print('Python', python_version())try:? ? let_us_cause_a_NameErrorexcept NameError as err:print(err,'--> our error message')Python3.4.1name'let_us_cause_a_NameError'isnotdefined-->ourerror message

next() 函數 and .next() 方法

因為next() (.next())是一個如此普通的使用函數(方法),這里有另外一個語法改變(或者是實現上改變了),值得一提的是:在 Python 2.7.5 中函數和方法你都可以使用,next()函數在 Python 3 中一直保留著(調用.next()拋出屬性異常)。

Python 2

print'Python', python_version()my_generator = (letterforletterin'abcdefg')next(my_generator)my_generator.next()

Python2.7.6'b'

Python 3

print('Python', python_version())my_generator = (letterforletterin'abcdefg')next(my_generator)

Python3.4.1'a'

my_generator.next()

---------------------------------------------------------------------------AttributeError? ? ? ? ? ? ? ? ? ? ? ? ? ? Traceback (most recentcalllast)in()----> 1 my_generator.next()AttributeError:'generator'object hasnoattribute'next'

For 循環變量和全局命名空間泄漏

好消息:在 Python 3.x 中 for 循環變量不會再導致命名空間泄漏。

在 Python 3.x 中做了一個改變,在What’s New In Python 3.0中有如下描述:

"列表推導不再支持[... for var in item1, item2, ...]這樣的語法。使用[... for var in (item1, item2, ...)]代替。也需要提醒的是列表推導有不同的語義:? 他們關閉了在 `list()` 構造器中的生成器表達式的語法糖, 并且特別是循環控制變量不再泄漏進周圍的作用范圍域."

Python 2

print'Python', python_version()i =1print'before: i =', iprint'comprehension: ', [iforiinrange(5)]print'after: i =', iPython2.7.6before: i =1comprehension:? [0,1,2,3,4]after: i =4

Python 3

print('Python', python_version())i =1print('before: i =', i)print('comprehension:', [iforiinrange(5)])print('after: i =', i)Python3.4.1before: i =1comprehension: [0,1,2,3,4]after: i =1

比較不可排序類型

在 Python 3 中的另外一個變化就是當對不可排序類型做比較的時候,會拋出一個類型錯誤。

Python 2

print'Python', python_version()print"[1, 2] > 'foo' = ", [1,2] >'foo'print"(1, 2) > 'foo' = ", (1,2) >'foo'print"[1, 2] > (1, 2) = ", [1,2] > (1,2)Python2.7.6[1,2] >'foo'=False(1,2) >'foo'=True[1,2] > (1,2) =False

Python 3

print('Python', python_version())print("[1, 2] > 'foo' = ", [1,2] >'foo')print("(1, 2) > 'foo' = ", (1,2) >'foo')print("[1, 2] > (1, 2) = ", [1,2] > (1,2))Python3.4.1---------------------------------------------------------------------------TypeError? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Traceback (most recent call last)in()1print('Python', python_version())---->2print("[1, 2] > 'foo' = ", [1,2] >'foo')3print("(1, 2) > 'foo' = ", (1,2) >'foo')4print("[1, 2] > (1, 2) = ", [1,2] > (1,2))TypeError: unorderabletypes: list() > str()

通過input()解析用戶的輸入

幸運的是,在 Python 3 中已經解決了把用戶的輸入存儲為一個str對象的問題。為了避免在 Python 2 中的讀取非字符串類型的危險行為,我們不得不使用raw_input()代替。

Python 2

Python2.7.6[GCC4.0.1(AppleInc. build5493)] on darwinType"help","copyright","credits"or"license"formore information.>>> my_input = input('enter a number: ')enter anumber:123>>> type(my_input)>>> my_input = raw_input('enter a number: ')enter anumber:123>>> type(my_input)

Python 3

Python3.4.1[GCC4.2.1(AppleInc. build5577)] on darwinType"help","copyright","credits"or"license"formore information.>>> my_input = input('enter a number: ')enter anumber:123>>> type(my_input)

返回可迭代對象,而不是列表

如果在 xrange 章節看到的,現在在 Python 3 中一些方法和函數返回迭代對象 -- 代替 Python 2 中的列表

因為我們通常那些遍歷只有一次,我認為這個改變對節約內存很有意義。盡管如此,它也是可能的,相對于生成器 --- 如需要遍歷多次。它是不那么高效的。

而對于那些情況下,我們真正需要的是列表對象,我們可以通過list()函數簡單的把迭代對象轉換成一個列表。

Python 2

print'Python', python_version()printrange(3)printtype(range(3))Python2.7.6[0,1,2]

Python 3

print('Python', python_version())print(range(3))print(type(range(3)))print(list(range(3)))Python3.4.1range(0,3)[0,1,2]

在 Python 3 中一些經常使用到的不再返回列表的函數和方法

zip()

map()

filter()

dictionary's .keys() method

dictionary's .values() method

dictionary's .items() method

更多的關于 Python 2 和 Python 3 的文章

下面是我建議后續的關于 Python 2 和 Python 3 的一些好文章。

移植到 Python 3

Should I use Python 2 or Python 3 for my development activity?

What’s New In Python 3.0

Porting to Python 3

Porting Python 2 Code to Python 3

How keep Python 3 moving forward

Python 3 的擁護者和反對者

10 awesome features of Python that you can't use because you refuse to upgrade to Python 3

Everything you did not want to know about Unicode in Python 3

Python 3 is killing Python

Python 3 can revive Python

Python 3 is fine

2014年07月26日發布

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,663評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,125評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,506評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,614評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,402評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,934評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,021評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,168評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,690評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,596評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,784評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,288評論 5 357
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,027評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,404評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,662評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,398評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,743評論 2 370

推薦閱讀更多精彩內容