2020 年 4 月 20 日,Python 2 的最後一個版本 2.7.18 釋出了,這意味着 Python 2 是真正的 EOL(end of life)了,一個時代終于落幕了。
Python 2.0 版本是在 2000 年釋出的,至今正好到 20 周年(差半年),一代版本竟然持續了這麼長時間。其中,2.7 版本是在 Python 3 推出後才釋出的,它在 2010 年釋出,至今已是 10 年之久。
事實上,Python 誕生了 30 年,但版本演進過程一直很慢,目前最新釋出的版本隻到 3.8.2。
對比一下相差幾歲的隔壁家選手,C++ 已經發展到了 20,JAVA 發展到了 14 ,PHP 到了 7.4,差距懸殊。
但是,版本釋出太頻繁,也不總是一件好事。就在 Python 程式員抱怨自己的 Python 2 項目還沒升 3 版本時,有些 JAVA 程式員還在維護 6、7 版本的項目呢。版本遷移之苦,大家彼此彼此,五十步笑百步。
程式設計語言跨版本間出現不相容的特性,幾乎是常态。很多時候,并不是說過去的設計是 bug,隻是因為程式設計語言也是某種“生命體”,它會學習其它語言,也會自我進化,是以就有新陳代謝。
擺脫舊的不相容性版本或者某些落後的設計,有時候需要挺漫長的過渡期。為了友善程式員遷移,核心開發者們形成了一些有效的慣例。
以 Python 為例,我知道有以下的幾種政策:
1、DeprecationWarning 提示
當使用過期的類或方法時,會出現 DeprecationWarning 告警。
例如,從 collections 子產品導入 ABC(Abstract Base Classes,即抽象基類)就是過期用法,會出現以下提示:
DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated since Python 3.3, and in 3.9 it will stop working
從 3.3 版本起,正确的用法是
from collections.abc import Iterable
,直到 3.9 版本時,會取消過期提示,出現報錯。
2、将子產品改名,約定為私有
在 Python 中,以單下劃線“_”開頭命名的變量,會被約定為私有的。如果在一個子產品中定義了私有變量,理論上它就不該被導出到其它子產品使用。
這種命名方式也被推廣到了标準子產品上。例如,在 Python 的極早期版本中有一個
thread
子產品,後來到 1.5.1 版本,以 thread 為基礎又推出一個更友善好用的
threading
子產品,也就是我們熟知的實作多線程的子產品。
為了擺脫/屏蔽舊的實作,Python 把 thread 子產品重命名為
_thread
,約定為私有的,這種方式很靈活,普通程式員不會感覺它的存在,骨灰級程式員卻可以用它實作更加低層的開發。
3、文檔中作 deprecated 提示
它跟 DeprecationWarning 是同樣的意思。之是以要單獨列出來,是因為在構思本文時,我正巧在 Python 3.8 文檔中發現了一則提示,忍不住分享一下。
文檔中說: @asyncio.coroutine 裝飾器不再支援基于
yield from
生成器實作的協程,需要顯式地寫成“asyc def”這種定義方式。
這意味着,3.8 版本對該特性來說就是個分界線,它将進入一個平穩的淘汰周期。
以上三種方式可謂是“除舊”,是面向過去的版本所做的。與它們相對應,就少不了“迎新”的過程,要面向未來的版本。
Python 中有時候會在目前版本中加入一些實驗性的特性,期待在未來版本中再完全地實作。而這,就需要給程式員們指出一些過渡性的提示。
例如,在《Python 3.9 性能優化:更快的 list()、dict() 和 range() 等内置類型》一文中,我就介紹了隐藏在 3.8 版本中的“vectorcall”協定,它要在 3.9 版本中才會真正地實作(而且不排除在未來還會繼續擴充)。
此外,還有一個很著名的例子:3.2 版本中推出的
concurrent.futures
标準庫(依據 PEP-3148)。
這是一個統合了多線程與多程序的異步開發庫,“concurrent”指的是并發,而“并發”概念可以囊括多線程與多程序的實作方式。
為什麼在“concurrent”下面要加一個“futures”呢?PEP-3148 中指出了這樣命名的三點原因,其中最後一點是:希望在将來(in the future)能夠添加和移動現有的跟并發相關的庫到
concurrent
庫下面。
也就是說,3.2 版本的
concurrent.futures
就是一種實驗性的設計,它是為将來更好的
concurrent
庫而作的準備。雖然說将來的最終實作,可能跟 PEP 中設想的不同,但是,這種面向将來的長遠考慮的設計思路,會給整個社群帶來某種預期和共同的信念。
好了,聊了這麼多,是時候收個尾了。
我從未真正開發或維護過 Python 2 的項目,是以在這個本應紀念它 EOL 的日子,所能想到的就是一個更具普遍性的“除舊迎新”的話題:舊的版本特性是如何逐漸退出的,新的版本特性又是如何逐漸加入的?
如果你喜歡這種風格的文章,歡迎搜尋關注公衆号“Python貓”。人生苦短,讓我們一起用 Python!
推薦閱讀:
本文首發位址:https://mp.weixin.qq.com/s/PIhtEIzBgy_ujcTeAQ2dxg
1、Python 3.9 性能優化,更快的 list()、dict() 和 range() 等内置類型:https://mp.weixin.qq.com/s/bjQjVmf7dP5fOqCS1cObqQ
2、PEP-3148:https://www.python.org/dev/peps/pep-3148
3、聊聊 Python 的内置電池:https://mp.weixin.qq.com/s/XzCqoCvcpFJt4A-E4WMqaA
4、聊聊 print 的前世今生:https://mp.weixin.qq.com/s/NuzfuH_zCZzcrmSFR04NHw