從2008年12月3日Python 3.0釋出,帶來了許多新特性,由於新版本採用了破壞向後相容性(Backward compatibility)的方式,不可避免地引發了許多2.x、3.x的爭戰問題,然而,從那之後又經過了七年多,Python 3.x的版本也持續推進到了3.5(於2015年9月13日釋出),現在的情況到底如何了呢?
破壞向後相容性的險路
時光回到2008年,許多人引頸期盼的新功能,包括在新出爐的Python 3.0(也被稱為Python 3000或Py3K)中,其中最引人注目的是Unicode的支援,將str/unicode做了個統合,並明確地提供了另一個bytes類型,解決了許多人處理字元編碼的問題,然而,其他語法與程式庫方面的變更,也破壞了向後相容性,導致許多基於Python 2.x的程式,無法直接在Python 3.0的環境中運行。
對程式語言而言,破壞向後相容性是條險路,歷史上少有語言能走這條路而獲得成功。許多語言都小心翼翼地在推出新版的同時,兼顧向後相容,代表之一就是Java,開發者雖然樂見既有的程式資產,在新版Java上運作(幾乎)都沒有問題,然後,代價就是越來越肥大的語言,而一些在其他語言看似不錯的特性,為了符合向後相容性保證,因而做了畸形地調整而出現在Java中,這使得處理一件任務時錯誤與正確的做法越來越多,同時並存於語言之中。
從這個層面來看,Python 3.0選擇破壞相容性,基本上是可以理解的,而Python 3.0演進的指導原則,正是「將處理事情的老方法移除,以減少特性的重複」,這符合PEP 20的規範,就是Python哲學中「做事時應該只有一種(也許也是唯一)明確的方式」之條目。
擁有著BDFL(Benevolent Dictator For Life),也就是「仁慈獨裁者」的Python創建者Guido van Rossum,也一路持續地推動著Python 3.x系列的前進,並逐步降低對Python 2.x的支援——Python 2.7是2.x最後一個版本,不再加入新特性,只會提供臭蟲與安全更新,而且僅支援至2020年,這是Guido van Rossum的最愛,而這種專制的推動,確實也符合仁慈獨裁者這個名號。
然而,從Python 3.0推出到現在,不斷地都有入門者在問,我要學Python 3.x,還是Python 2.x?由於難以選擇,許多介紹文件或書藉,也不得不同時介紹2.x與3.x兩個版本(像是O'Reilly那1600多頁的《Learning Python》);儘管有2to3這個工具可以轉換程式碼,它也不能發現所有的問題;漸漸地,也開始有了〈Python 3 is killing Python〉這類的文章出現,預測著Python社群將會分裂,甚至既有擁護者將會離開Python。
從Python 3.0到3.5
儘管破壞向後相容性的語言,多半不會有什麼好的結果,然而,就這幾年來Python 3.x與2.x的發展來看,過程與那些失敗了的語言不太一樣,社群中接受與呼籲Python 3.x的聲音也越來越多,Python本身也以每隔一年左右推出一個3.x版本前進著,過程似乎也並不是官方一廂情願地推進,而是不斷地傾聽著社群聲音,不斷地為相容轉換做出了努力。
首先眾所皆知的,如果想在Python 2.x中就開始使用Python 3.x的一些特性,可以試著from __future__ import你想要的模組,例如最基本的from __future__ import print_function,就可以開始使用print函式,以相容方式來撰寫輸出陳述。
在Python官方的〈Python2orPython3〉也整理了許多相容轉換的相關資源,其中指出,Python 3.0的一些較不具破壞性的特性,回饋(backport)到Python 2.6之中,而Python 3.1的特性,回饋到了Python 2.7之中;回饋也反過來從2.x至3.x,例如,在Python 3.3中又支援了u"foo"來表示unicode字串,b"foo"來表示byte字串,相容性同時在2.x與3.x之間前進著,試著讓語法有更多交集。
Python 3.x本身也不斷地吸納社群經驗,舉例來說,Python 3.3中包含了venv,相當於過去社群用來建立虛擬環境的virtualenv工具;Python 3.4本身就包含了pip,這是過去社群中,建議用來安裝Python相關模組的工具;Python 3.5更納入了type hints,儘管它本身是個動態定型語言,然而,這特性有助於靜態分析、重構、執行時期類型檢查,對大型專案開發有顯著的幫助,而且對既有程式碼不會有影響。
儘管Python 3.x本身不斷在相容性與新特性上,釋出利多(有機會應該好好看看各版本的Release資訊),社群不買單的話,基本上也是徒勞無功。
實際上就學習Python本身來說,以2.x與3.x作為開始,並不是太大的問題,就現代開發者而言,接觸多個語言本來就是常態,更何況是在2.x與3.x交集如此多的Python之中,學習或轉換本身並不是難事。
然而,一個現實的問題是,新系統要開發時,究竟要基於Python 2.x或是Python 3.x?最好的方式是寫出能同時相容於2.x與3.x版本上的程式碼,除了要建立良好的程式碼慣例之外,社群中還有著six這類的套件,可以寫出相容2.7和3的程式碼基礎。
許多基於Python 2.x的程式庫或框架,也不斷地往Python 3.x遷移,像是最近引起我注意的是Django,其新版本已經支援至Python 3.4,官方的Tutorial也是基於此版本而改寫,一些科學運算套件,像是Numpy、SciPy等,也有著支援Python 3.x的版本。
想要知道其他程式庫是否有支援Python 3.x,有個〈PYTHON 3 WALL OF SUPERPOWERS〉,可以作為不錯的參考,其中列出了200個程式庫,174個標示為綠色,表示支援Python 3.x,在2014年左右,仍有35個被標示為不支援Python 3.x的紅色,目前則只剩下26個程式庫是紅色狀態。
另一方面,著名的Linux系統,目前多半也同時預載了Python 2.x與3.x,例如Ubuntu從13.04起,就預載了Python 3.x(必須使用python3指令),Ubuntu也持續移除系統中對Python 2.x的依賴,並計畫於16.04版本中,能夠全面採用Python 3.x,而且不再預載Python 2.x。
不再是2008年的Python 3.0
曾有人說過,Guido van Rossum最大的問題,就是沒有斷然處置Python 2.x,還讓2.7持續維護至2020年,因而造成在抉擇2.x或3.x時如此多的問題,不過,2008年到現在,持續在相容性與接納社群意見上做出的努力,看來社群似乎因為有了這七年的時間,才得以逐步轉換,提高了Python 3.x的接受度。
當然,有些程式庫確實還死守在Python 2.x,而且有些甚至還聲明,未來絕不會有支援3.x的版本,然而,這並不表示現在回應「Python 2.x與3.x,我要學(用)哪個?」這類問題時,還只是像2008年剛開始的那時,能不假思索地脫口而出「因為許多程式庫還不支援Python 3,所以建議還是學(用)Python 2.x好了」。
現在的Python 3.x畢竟不再是2008年的Python 3.0了,正如在選擇一門語言,或者是調查某個程式庫是否可以採用時,必須有著諸多考量,像是更新(update)的時間、修改記錄(changelog)、修正問題(issue)的速率、作者等,現在選擇使用Python 2.x或是Python 3.x,最好的方式是做更全面的調查、尋找、評估可靠的資源。
畢竟,「許多程式庫還不支援Python 3」這理由,就現今而言已經太草率了,所謂的許多程式庫,到底是哪些程式庫呢?而你的「許多」又是哪個年代的「許多」呢?