1. 程式人生 > >Python 2.x 與 Python 3.x 的區別

Python 2.x 與 Python 3.x 的區別

前言

如果你是剛接觸 Python 的初學者,那你可能是直接學習 Python 3.x 版本。對於 Python 2.x 的版本是不會有所接觸。官方也宣佈在 2020 停止對 Python 2.x 的維護。我也建議初學者直接去學 Python 3.x 版本。但我們還是要去了解下 Python 3.x 與 Python 2.x 之間都有哪些改變,通過對比能讓你對 Python 有更加深刻的理解。並且在很多面試過程中,面試官都會問:Python 2.x 與 Python 3.x 的區別。今天就給大家列舉 Python 3.0 主要改變的幾個方面。

Py3K

Python 的 3.0 版本,常被稱為 Python 3000,或簡稱 Py3K。

為了照顧現有程式,Python 2.6 作為一個過度版本,基本使用了 Python 2.x 得語法和庫,同時考慮了向 Pythn 3.0 得遷移,允許使用部分 Python 3.0 的語法與函式。

Python 3.0 的變化主要在以下幾個方面:

1 print 函式

print 語句沒有了,取而代之的是 print() 函式。Python 2.6 與 Python 2.7 部分地支援這種形式的 print 語法。在 Python 2.6 與 Python 2.7 裡面,以下三種形式是等價的:

print "fish"
print ("fish") # 注意 print 後面有個空格
print("fish") # print() 不能帶有任何其它引數

然後,Python 2.6 實際已經支援新得 print() 語法:

from __future__ import print_function
print("fish", "panda", sep=", ")

2 Unicode

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

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

由於 Python 3.x 原始碼檔案預設使用 uft-8 編碼,這就使得以下程式碼是合法的:

>>> 中國 = 'china'
>>> print(中國)
china

Python 2.x

>>> str = '我愛北京天安門'
>>> str
'\xe6\x88\x91\xe7\x88\xb1\xe5\x8c\x97\xe4\xba\xac\xe5\xa4\xa9\xe5\xae\x89\xe9\x97\xa8'
>>> str = u'我愛北京天安門'
>>> str 
u'\u6211\u7231\u5317\u4eac\u5929\u5b89\u95e8'

Python 3.x

>>> str = "我愛北京天安門"
>>> str
'我愛北京天安門'

3 除法運算

Python 中的除法較其它語言顯得非常高階,有套很複雜的規則。Python 中的除法有兩個運算子,/ 和 // 首先來說下 / 除法:

在 python 2.x 中 / 除法就跟我們熟悉的大多數語言,比如 Java、C 差不多,整數相除的結果是一個整數,把小數部分完全忽略掉,浮點數除法會保留小數點的部分得到一個浮點數的結果。

在 python3.x 中 / 除法不再這麼做了,對於整數之間的相除,結果也會是浮點數。

Python 2.x

>>> 1 / 2
0
>>> 1.0 / 2.0
0.5

Python 3.x

>>> 1/2
0.5

而對於 // 除法,這種除法叫做 floor 除法,會對除法的結果自動進行一個 floor 操作,在 python 2.x 和 python 3.x 中是一致的。

而 floor 除法指的是返回數字的下舍整數,在 Python 中有個 floor 函式,它不能直接訪問,需要匯入 math 模組,通過靜態物件呼叫該方法。舉個例子:

import math   # This will import math module
print "math.floor(-45.17) : ", math.floor(-45.17)

輸出結果:

math.floor(-45.17) :  -46.0

python 2.x:

>>> -1 // 2
-1

注意的是並不是捨棄小數部分,而是執行 floor 操作,如果要擷取小數部分,那麼需要使用 math 模組的 trunc 函式

python 3.x

>>> import math
>>> math.trunc(1 / 2)
0
>>> math.trunc(-1 / 2)
0

4 異常

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

捕獲異常的語法由 except exc, var 改為 except exc as var。

使用語法 except (exc1, exc2) as var 可以同時捕獲多種類別的異常。 Python 2.6 已經支援這兩種語法。

  1. 在 2.x 時代,所有型別的物件都是可以被直接丟擲的,在 3.x 時代,只有繼承自 BaseException 的物件才可以被丟擲。
  2. 2.x raise 語句使用逗號將丟擲物件型別和引數分開,3.x 取消了這種奇葩的寫法,直接呼叫建構函式丟擲物件即可。
    在 2.x 時代,異常在程式碼中除了表示程式錯誤,還經常做一些普通控制結構應該做的事情,在 3.x 中可以看出,設計者讓異常變的更加專一,只有在錯誤發生的情況才能去用異常捕獲語句來處理。

5 xrange

在 Python 2 中 xrange() 建立迭代物件的用法是非常流行的。比如: for 迴圈或者是列表/集合/字典推導式。

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

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

惰性求值:惰性求值,也就是延遲求值,表示式不會在它被繫結到變數之後就立即求值,而是等用到時再求值。

作用:這個特性可以解決一些巨大甚至無限的集合列表,延遲求值的一個好處是能夠建立可計算的無限列表,而沒有妨礙計算的無限迴圈或大小問題。

Python 中的很多方法沒有直接返回列表,而是返回了一個可迭代的 generator (生成器)物件,這便是 python 的惰性求值。

在 Python 3 中,range() 是像 xrange() 那樣實現以至於一個專門的 xrange() 函式都不再存在(在 Python 3 中 xrange() 會丟擲命名異常)。

import timeit
n = 10000
def test_range(n):
    return for i in range(n):
        pass
def test_xrange(n):
    for i in xrange(n):
        pass   

Python 2

print 'Python', python_version()
print '\ntiming range()' 
%timeit test_range(n)
print '\n\ntiming xrange()' 
%timeit test_xrange(n)
Python 2.7.6
timing range()
1000 loops, best of 3: 433 µs per loop
timing xrange()
1000 loops, best of 3: 350 µs per loop

Python 3

print('Python', python_version())
print('\ntiming range()')
%timeit test_range(n)
Python 3.4.1
timing range()
1000 loops, best of 3: 520 µs per loop
print(xrange(10))
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-5-5d8f9b79ea70> in <module>()
----> 1 print(xrange(10))
NameError: name 'xrange' is not defined

6 八進位制字面量表示

八進位制數必須寫成 0o777,原來的形式 0777 不能用了;二進位制必須寫成 0b111。

新增了一個 bin() 函式用於將一個整數轉換成二進位制字串。 Python 2.6 已經支援這兩種語法。

在 Python 3.x 中,表示八進位制字面量的方式只有一種,就是 0o1000。

pyhon 2.x

>>> 0o1000
512
>>> 01000
512

python 3.x

>>> 01000
  File "<stdin>", line 1
    01000
        ^
SyntaxError: invalid token
>>> 0o1000
512

7 不等運算子

Python 2.x 中不等於有兩種寫法 != 和 <>

Python 3.x 中去掉了 <>,只有 != 一種寫法。

8 去掉了 repr 表示式 ``

Python 2.x 中反引號 `` 相當於 repr 函式的作用

Python 3.x 中去掉了 `` 這種寫法,只允許使用 repr 函式。

repr 是什麼:repr() 函式將物件轉化為供直譯器讀取的形式,返回一個物件的 string 格式。

9 多個模組被改名(根據 PEP8)

httplib, BaseHTTPServer, CGIHTTPServer, SimpleHTTPServer, Cookie, cookielib 被合併到 http 包內。StringIO 模組現在被合併到新的 io 模組內。 new, md5, gopherlib 等模組被刪除。 Python 2.6 已經支援新的 io 模組。

取消了 exec 語句,只剩下 exec() 函式。 Python 2.6 已經支援 exec() 函式。

10 資料型別

1)Py3.X 去除了 long 型別,現在只有一種整型——int,但它的行為就像 2.X 版本的 long。

2)新增了 bytes 型別,對應於 2.x 版本的八位串,定義一個 bytes 字面量的方法如下:

>>> b = b'china' 
>>> type(b) 
<type 'bytes'> 

str 物件和 bytes 物件可以使用 .encode() (str -> bytes) or .decode() (bytes -> str) 方法相互轉化。

>>> s = b.decode() 
>>> s 
'china' 
>>> b1 = s.encode() 
>>> b1 
b'china' 

3)dict 的 .keys()、.items 和 .values() 方法返回迭代器,而之前的 iterkeys() 等函式都被廢棄。同時去掉的還有 dict.has_key(),用 in 替代它。

11 開啟檔案

原先有兩種開啟方式:

file( ..... )
或 
open(.....)

現在改成只能用

open(......)

12 從鍵盤錄入一個字串

原先:

raw_input("提示資訊")

現在:

input("提示資訊")

在 python2.x 中 raw_input() 和 input( ),兩個函式都存在,其中區別為:

raw_input():將所有輸入作為字串看待,返回字串型別
input():只能接收"數字"的輸入,在對待純數字輸入時具有自己的特性,它返回所輸入的數字的型別(int, float )
在 python3.x 中 raw_input() 和 input( ) 進行了整合,去除了 raw_input(),僅保留了 input() 函式,其接收任意任性輸入,將所有輸入預設為字串處理,並返回字串型別。