Python 2 和 Python 3,一直是一個話題。Brett Cannon 是 Python 的核心開發者,聽聽他關於 Python3 的看法。
本月我在 Puppy 上開展了一個問答活動(Puget Sound Python使用者組),讓我最終解釋了為什麼 Python 3 會出現以及整個的 string/bytes 處理機制。我因此受到讚揚這讓我很驚訝,因為原本我天真的認為大家都清楚為什麼 Python 3 會出現。回想起來我真是太傻,竟然認為大部分人(不管是剛接觸 Python 或者已經有一段時間)應該要麼已經被告知要麼有好奇心驅使去搜尋獲取一個解釋。所以這篇博文打算簡單的解釋一下為什麼 Python 3 會存在,特別是我們為什麼選擇打破整個向後相容 unicode/str/bytes,因為這使得程式碼移植到 Python 3 非常棘手。
在 Python 2 中文字和二進位制資料是一個爛攤子
快,下面的文字代表什麼語義?
1 |
'abcd' |
如果你是 Python 3 的使用者,你會說它是一個按照 “a”、”b”、”c”、”d”順序包含四個字母的字串。
如果你是 Python 2 的使用者,你也會說同樣的話。你同樣也可能會說它是代表 97、98、99、100 的陣列。事實上在 Python 2中對於 str 代表的含義有兩種正確的回答,這改變了語言的初衷。所以在 Python 3 中答案是唯一的。
《Python之禪》裡講“應該有一個“應該有一個––最好只有一個顯而易見的方式去實現”。文字既能代表文字資料又能代表二進位制資料這很麻煩。一旦物件 脫離你的控制,你將無從知曉。比如,如果你從網路上讀到一些東西,你得小心判別這個 str 是代表二進位制資料還是文字資料。或者你的程式碼裡有一個bug,它是用來將 str 變換成文字資訊––或者完全別的東西––但你搞砸了,不小心跳過了這一步。由於 str 潛在的代表兩種型別,此類錯誤發生的時候,我們很難意識到。
也許你會說這些問題在 Python 2 中完全可以解決,只要你用 Unicode 而不是 str 去代表文字。雖然說的很對,但現實中人們不會那樣去做。人們要麼很懶,試著去避免解碼到 Unicode 帶來的額外工作,要麼對效能要求很高,不想因為解碼帶來額外的損失。無論哪種情況,它都假設你程式碼足夠好而避免了那些麻煩,但我們都清楚人不是完美的都會犯錯。如果人們寄希望於在 Python 2 中寫出沒有 bug 的程式碼能夠成真,我也不會總是聽到幾乎每個將他們的工程轉向 Python 3 的人講他們在程式碼中間文字和二進位制資料編解碼的潛在 bug。
避免 bug 是一件很重要的事情,但卻經常被人遺忘。簡化語言以及移除 str 可能代表的模糊含義會減少程式碼的出錯率。《Python 之禪》指出“顯勝於隱”的一個原因是: 歧義和隱性知識使得程式碼不容易溝通,進而容易出錯,導致 bug。通過迫使開發者明確地分離出他們的二進位制資料和文字資料,會使程式碼減少某一類的 bug。
其他語言都已經完全支援 Unicode(出於好的初衷)
人們有時會忘記 Python 有多久的歷史了:Guido 在1989年12月開始編寫 Python,在1991年2月開源釋出。這意味著它早於在1991年10月釋出的第一版 Unicode 標準。在接下來幾年中,晚於 Unicode 標準出現的語言都選擇在支援 Unicode 編碼的基礎上實現自己的 str 型別。這讓 Python 2 處於尷尬的境地。直到2004年開始引發關注(那時 Python 3 開始醞釀),但它爭辯說對於Unicode文字的弱支援是基於unicode 完全可選 ,人們不會在所有的文字資訊上使用它。
支援 Unicode 和來自任何語言的的文字是非常重要的。Python 是一門面向世界的語言,而不只是那些支援 ASCII 碼覆蓋的羅馬數字的語言。這就是為什麼 Python 3 在處理文字時選擇“要麼使用 Unicode,要麼就乾脆不支援”的原因。官方宣稱所有的 Python 3 程式碼都將支援世界上的每一個人,無論寫程式碼的開發者是否有著明確的意圖。在 Python 2 中,按照能夠正確支援 Unicode 型別文字資訊將專案分為兩類;在 Python 3 中則不存在此類問題,並且它支援所有語言。
我們設想 Python 將更越來越受歡迎
在2004年我們開始編寫 PEP 3000 進而開始設計 Python 3 (注:PEP 最初編號為 3000,但我們把它重新編號為 3100,這樣我們就可以藉助 編號 3000 的 PEP 來開發 Python 3)。我們清楚 Python 的受歡迎程度在不斷上升,我們也希望能夠延續這種勢頭(謝天謝地,目前如此)。但這也同時意味著如果我們想及時修正所有的設計缺陷來保證它的受歡迎度,最好趁現在而不是以後。我們設想 Python 3 相較於 Python 2 會持續更長一段時間,而 Python 2.7 僅僅是用來維護以前遺留的專案,而不會用於新專案中,那用 Python 3 寫出的程式碼一定會多於用 Python 2 的。所以我們決定來承受由 Python 2 向 3 轉型之痛。並且在這種設想下開發了 Python 3。想要知道 Python 3 的程式碼量能否趕超 Python 2,很顯然需要數十年時間。
我們再也不會做這種打破向後相容性的事情
我們團隊已經下定決心再也不會讓諸如 unicode/str/bytes 這樣重大的改變隨意發生。當我們決心開始 Python 3 的時候,我們設想同時希望社群能夠像 Python 做的那般並且釋出支援 Python 2的最終版本,接著切換到 Python 3 的功能開發中,只對 Python 2 做bug修復版本。這顯然沒有發生,同時也給我們上了一課。加上我們也沒有發現在語言的基礎設計中間存在需要做出如此重大改變來滿足需要的缺陷。也希望 Python 4 不要發生比從標準庫中移除廢棄模組更激烈的改變。
結論
這就是 Python 3 為什麼是這個樣子的原因。我們意識到很多 bug 都是由於在 Python 2 中對 str 型別超負荷的使用。所以我們在 Python 3 中通過將文字資料和二進位制資料分離來修正它。它也促使所有的文字資訊都支援 Unicode,從而使得工程更容易在多種語言下工作。我們做出了改變,因為我們明白這種改變越早越好。我們在轉型期曾經認為社群最終會摒棄 Python 2 和我們一道,但結局並非如此,相反我們花費了更多時間並且用一個 Python 2/3 的相容子集來實現這種過渡。
打賞支援我翻譯更多好文章,謝謝!
打賞譯者
打賞支援我翻譯更多好文章,謝謝!
任選一種支付方式