Python 2 與 Python 3 的差別對比

這篇文章總結了一些與Python2.6相比Python3.0中的新特性.Python3是一個不向後兼容的版本,有了不少的改變,這些對於Python開發者來講是很是重要的,雖然多數人說Python3真正流行起來還須要一段時間,可是Python3確實有了很大的改進,如今也是時間來學習Python3了。在真正理解Python3中的一些變化以後,會發現其實Python3的變化並無想象的那麼多,主要是修復了一些使人討厭的地方。 html

通常在每個發行版源碼的Misc/NEWS文件中詳細描述了每個細小的變化。 python

一、常見的障礙

1.1 Print是一個函數

在Python3中print是個函數,這意味着在使用的時候必須帶上小括號,而且它是帶有參數的。 緩存

old: print "The answer is", 2+2
new: print("The answer is", 2+2)  

old: print x,      # 末尾加上逗號阻止換行  
new: print(x, end="") # 使用空格來代替新的一行  

old: print >>sys.staerr, "fatal error"  
new: print ("fatal error", file=sys.stderr)  

old: print (x, y)   # 打印出元組(x, y) 
new: print((x, y))  # 同上,在python3中print(x, y)的結果是跟這不一樣的

在Python3中還能夠定義分隔符,使用參數sep來指定. 函數

print("There are <", 2+5, ">possibilities", sep="")

上面代碼的結果以下: 工具

There are <7> possibilities

注意: 學習

  • print()函數不支持Python2.X中print中的「軟空格」。在Python2.X中,print "A\n", "B"的結果是"A\nB\n";而在Python3中print("A\n", "B")的結果是"A\n B\n"。 ui

  • 在剛開始使用Python3的時候,你會發現你常常在交互模式下你仍是常用老式的語法print x,是時候鍛鍊你的手指用print(x)來取代它啦。 編碼

  • 若是你的項目比較大,而又想升級到Python3的時候,不用擔憂,2to3這個工具會將全部的print語句轉換爲print()函數。 spa

1.2 使用Views和Iterators代替Lists

  • dict的方法dict.keys(),dict.items(),dict.values()不會再返回列表,而是返回一個易讀的「views」。這樣一來,像這樣的語法將再也不有用了:k = d.keys();k.sort(),你可使用k = sorted(d)來代替。sorted(d)在Python2.5及之後的版本中也有用,可是Python3效率更高了。
d = {'a': 1}
d.keys()     # dict_keys(['a'])  
d.items()    # dict_items([('a', 1)])  
d.values()   # dict_values([1])  
k = d.keys(); k.sort()     # AttributeError: 'dict_keys' object has no attribute 'sort'
  • 一樣,dict.iterkeys(),dict.iteritems(),dict.itervalues()方法也再也不支持。
  • map()和filter()將返回iterators。若是你真的想要獲得列表,list(map(...))是一個快速的方法,可是更好的方法是使用列表推導(尤爲是原代碼使用了lambda表達式的時候),或者重寫原來的代碼,改成不須要使用列表。特別是map()會給函數帶來反作用,正確的方法是改成使用for循環,由於建立一個列表是很是浪費的事情。 .net

  • Python3中的range()函數跟Python2.X的xrange()函數的做用是同樣的,這樣可使用任意的數字,Python3中去除了xrange()函數。

  • zip()在Python3中返回的是一個迭代器。

1.3 比較符

     Python3簡化了比較符。

  • 在使用比較符(<,<=,>=,>)時,當相比較的操做數的排序是沒有意義的時候將會拋出TypeError異常,所以像1 < '',0 > None,len <= len這樣的語句再也不合法了。None < None也會拋出TypeError異常,而不是返回False。你應該明白了,胡亂的比較是沒有意義的,相比較的元素必須是可以比較的才行。須要注意的是,==和!=不包括在內,由於不通類型的,沒法比較元素老是不等於另外一個的。

  • builtin.sorted和list.sort()再也不有提供比較函數的cmp參數,只有參數key和reverse。

  • cmp()函數應該當作被去除了,__cmp__()特殊方法也再也不支持。在須要的時候使用__lt__,__eg__和__hash__。

1.4 整型數

  • 從本質上來講,long重命名了int,由於在內置只有一個名爲int的整型,但它基本跟以前的long同樣。

  • 像1/2這樣的語句將返回float,即0.5。使用1//2來獲取整型,這也是以前版本所謂的「地板除」。

  • 移除了sys.maxint,由於整型數已經沒了限制。sys.maxsize能夠用來當作一個比任何列表和字符串下標都要大的整型數。

  • repr()中比較大的整型數將再也不帶有L後綴。

  • 八進制數的字面量使用0o720代替了0720。

1.5 Text Vs. Data 代替 Unicode Vs. 8-bit

     Python3中改變了二進制數據和Unicode字符串。

  • Python3使用文本和(二進制)數據的理念代替以前的Unicode字符串和8-bit字符串,全部的文本默認是Unicode編碼。使用str類型保存文本,使用bytes類型保存數據。當你混淆文本和數據的時候Python3會拋出TypeError的錯誤。

  • 不能再使用u"..."字面量表示unicode文本,而必須使用b"..."字面量表示二進制數據。

  • 由於str和bytes不能弄混,因此你必須顯式地將他們進行轉換。使用str.encode()將str轉換爲bytes,使用bytes.decode()將bytes轉換爲str,也可使用bytes(s, encoding=...)和str(b, encoding=...)。

  • str和bytes都是不可變的類型,有一個分離的可變類型的bytearray能夠保存緩存的二進制數據,全部可以接受bytes的API都可以使用bytearray。這些可變的API是基於collections.MutableSequence的。

  • 移除了抽象類型basestring,使用str代替。

  • 文件默認使用文本類型打開,這也是open()函數默認的。若是要打開二進制文件必須使用b參數,不然會出現錯誤,而不會默默地提供錯誤的數據。

  • 文件名都使用unicode字符串傳入和輸出,變量名也是,因此可使用中文做爲變量名,例如 中國="China"; print(中國) 。關於 python2 的編碼問題請參考:詳解python中文編碼與處理 http://my.oschina.net/leejun2005/blog/74430

  • 一些關於系統的API,如os.environ和sys.argv,當系統容許bytes而且不能正常轉換爲unicode的話,也會出現問題。因此,將系統的LANG設置好是最好的作法。

  • repr()函數再也不轉義非ASCII字符。

  • 代碼默認爲UTF-8編碼。

  • 移除了StringIO和cStringIO。加入了io模塊,並分別使用io.StringIO和io.BytesIO分別用於text和data。

二、語法改變

2.1 新增語法

  • 函數變量和返回值annotations

  • Keyword-only變量。

  • nonlocal聲明。使用nonlocal x能夠直接引用一個外部做用域的變量,但不是全局變量。

  • 擴展了迭代的解包。

(a, *rest, b) = range(5)  
a   # 0
rest # [1,2,3]
b   # 4
  • 字典推導。{k: v for k, v in stuff }。
t = ((1,1), (2,2))  
d = {k: v for k, v in t}  
d # {1: 1, 2: 2} 
  • 集合推導。{x for x in stuff},與set(stuff)效果同樣,可是更加靈活。

  • 八進制字面量0o720。

  • 二進制字面量0b1010,至關於新的內置函數bin()。

  • 字節字面量b或者B,至關於新的內置函數bytes()。

2.2 改變的語法

  • 將except exc, var改成except exc as var。

  • 新的元類語法。

# old  
class C:
    __metaclass__ = M
    ....  

# new  
class C(metaclass=M):  
    ....


  • 列表推導再也不支持[... for var in item1, item2, ...],必須寫成[... for var in (item1, item2,...)]。
  • 省略號...做爲連續表達式能夠用於任何地方,以前只能用於分片中。可是必須連續寫,以前帶空格的. . .再也不支持。

2.3 移除的語法

  • 移除了元組的解包。不能再寫def foo(a, (b, c)): ....,須要寫成def foo(a, b_c):b, c = b_c。

  • 移除<>,使用!=代替。

  • exec()不能再做爲關鍵詞,只能做爲一個函數。而且exec()再也不支持流變量,如exec(f)需寫成exec(f.read())。

  • 整型不支持l/L後綴。

  • 字符串不支持'u/U'前綴。

  • from module import *只能用在模塊級,在函數中不可以使用。

  • 全部不以.開始的import語句均做爲絕對路徑的import對待。

  • 移除了經典類。


三、推薦閱讀:

使用 2to3 將代碼移植到 Python 3

http://woodpecker.org.cn/diveintopython3/porting-code-to-python-3-with-2to3.html

Moving from Python 2 to Python 3

http://ptgmedia.pearsoncmg.com/imprint_downloads/informit/promotions/python/python2python3.pdf

相關文章
相關標籤/搜索