1. 程式人生 > >深入淺出帶你瞭解Python2與Python3的異同

深入淺出帶你瞭解Python2與Python3的異同

最近C語言的學習告一段落,為了新的演算法學習開始重新撿起python。和兩年前不同,這次我選擇了最新的3.6而不是2.7。當然,入手的教材都是3的語言描述。為了簡單的瞭解2和3的區別,我在網上翻閱了不少資料,分享給大家。

儘管版本在不斷跌進,但是人們總是喜歡懷舊。比如現在還有人在用windows server 2002,儘管已經被微軟停止更新,再比如還有人在用Python 2.7版本,儘管Python 3.6版本已經正式釋出。Python 3.x引入了一些與Python 2.7不相容的關鍵字和特性,在Python 2.7中,使用者其實可以通過內建的__future__模組匯入這些新內容。當然,你也可以同時使用2.7和3.6幾個版本。

Python3.x引入了一些Python2不相容的關鍵字和特性,在Python2中可以通過內建的__future__模組匯入。如果你計劃對你的程式碼提供Python3.x支援,推薦使用__future__模組。舉例,如果我們想要在Python2中有Python3.x的整數除法,我們可以通過如下匯入:

__future__模組的更多功能在下表中列出:

特性

可選

強制

作用

nested_scopes

2.1.0b1 2.2 PEP 227:靜態巢狀的範圍

generators 2.2.0a1 2.3 PEP 255:簡單生成器

division 2.2.0a2 3.0 PEP 238

:修改除法運算子

absolute_import 2.5.0a1 3.0 PEP 328:匯入:多行和絕對/相對

with_statement 2.5.0a1 2.6 PEP 343:“with” 語句

print_function 2.6.0a2 3.0 PEP 3105:列印函式

unicode_literals 2.6.0a2 3.0 PEP 3112:Python 3000位元組文字

(源:[https://docs.python.org/2/library/__future__.html](https://docs.python.org/2/library/__future__.html#module-__future__))

print函式

囉嗦了點,print語法的變化可能是最廣為人知的更改,但仍值得一提:print語句被print函式取代,表示我們必須用圓括號將想列印的物件引起來。

Python2不需要圓括號,相比之下,Python3以Python2沒有圓括號的方式呼叫print函式會丟擲SyntaxError異常。

注意:

上面Python2列印"Hello, World"的例子看起來很“正常”。但是,如果括號中有多個物件,我們會建立一個元組,因為Python2中的print是語句,不是函式呼叫。

整數除法

如果你正在移植程式碼或在Python2上執行Python3的程式碼,這種變化特別危險,因為整數除法行為的變化常常不能引起人們的注意(它不丟擲SyntaxError異常)。

所以,在我的Python3指令碼中,我仍然傾向於使用float(3)/2或3/2.0而不是3/2,這樣可以為Python2的小夥伴們省去一些麻煩(反之亦然,我建議在Python2的指令碼中使用from __future__ import division)。

Unicode

Python2有ASCII str()字串型別,獨立的unicode型別,但是沒有byte位元組型別。

現在,Python3中,我們終於有Unicode(utf-8)字串和2位元組類︰byte和bytearrays。

xrange

xrange()的用法在Python2.x中非常流行,用於建立一個迭代物件,例如,在一個for迴圈或列表/字典解析。

這個行為非常類似於生成器(即“惰性計算”),但在這裡的xrange-iterable是不可窮舉的——意味著,你可以無限地迭代下去。

由於“惰性計算”,如果你只遍歷一次的話(例如,在一個for迴圈中)xrange()通常是更快的。然而,相比於1次迭代,不建議重複迭代多次,因為每一次迭代都會從頭開始。

在Python3中,range()實現了類似xrange()的功能,因此專門的xrange()函式不存在了(在Python3中使用xrange()會丟擲一個NameError異常。)

Python3中range 物件的__contains__方法

另一個值得一提的是:Python3.x中,range有一個新的__contains__方法(多謝Yuchen Ying指出來)。__contains__方法可以顯著地加快Python3.x對整型和布林型別的查詢。

根據上面的timeit變數結果可以看出,整數型別的查詢比浮點數型別的查詢快60,000倍。然而,在Python2.x中range和xrange沒有__contains__方法,對整型和浮點型別的查詢差異不會太大。

下面__contain__方法的“證明”目前還沒有加入到Python2.x中。

關於Python2和Python3速度差異的說明

一些人指出了Python3 range()和Python2 xrange()的速度差異。因為它們實現了相同的方式,就會有相同的速度。然而,有這樣一個事實:Python3通常慢於Python2。

引發異常

Python2接受“新”、“舊”兩種語法格式,而Python3會堵塞(會引發SyntaxError異常),如果我們不將異常引數括在括號裡:

在Python3中引發異常的正確方式:

處理異常

此外在Python3中對異常的處理略有改變。在Python3中,現在我們必須使用"as"關鍵字。

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

next()(.next())是一種常用的函式(方法),這是另一種語法更改(或者說在執行時更改)值得一提:在Python2.7.5中你可以使用next()函式和.next()方法,在Python3只保留了next()函式(呼叫.next()方法會引發AttributeError異常)。

For迴圈變數和全域性名稱空間洩漏

好訊息是:在Python3.x for迴圈中的變數不會影響全域性名稱空間了!

這裡回頭看下Python3.x中的更改和新特性描述,如下所述:

“列表解析不再支援的語法 [... for var in item1, item2, ...]。使用[... for var in (item1, item2, ...)]語法代替。此外請注意,列表解析有不同的語義:他們更接近於list()建構函式內部生成器表示式的語法糖,特別是迴圈控制的變數不再影響周圍範圍。”

比較unorderable型別

在Python3中另一個不錯的改變是:如果我們嘗試比較unorderable型別,會引發TypeError異常。

通過input()解析使用者輸入

幸運的是,input()函式在Python3中被修復了,因此它將使用者的輸入儲存成字串物件。為了避免在Python2中讀取非字串型別的輸入,我們必須使用raw_input()函式。

返回可迭代物件而非列表

正如我們已經在xrange章節看到的,在Python3中,一些函式和方法返回可迭代物件,而不是Python2中的列表。

因為我們通常只遍歷一次,我認為這種變化非常合理的節省記憶體。然而,相比於生成器,如果需要的話遍歷多次也是可能的,那麼這種情況下就不那麼有效了。

對於那些確定需要列表物件的情況,我們可以通過list()函式簡單地將可迭代物件轉換成列表。

一些更常用的函式和方法在Python3中不再返回列表了:

zip()

map()

filter()

字典的.keys()方法

字典的.values()方法

字典的.items()方法

關於Python2和Python3更多文章

這裡是一些我推薦的關於Python2和Python3的好文章供後續學習。

// 移植到Python3

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

// 支援和反對Python3

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

英文原文:http://sebastianraschka.com/Articles/2014_python_2_3_key_diff.html

譯者:leisants