1. 程式人生 > >力壓 Java 與 C 的 Python 現狀如何了?

力壓 Java 與 C 的 Python 現狀如何了?

轉眼間,2018 年已進入倒計時階段,回憶起這一年中程式語言界的發展,過得風生水起的語言非 Python 莫屬。而它的火熱和人工智慧產業的爆發不無關係,但全域性來看,得益於 AI 的 Python 並非止於 AI,Python 還在系統程式設計、多媒體應用、資料庫程式設計、Web、爬蟲等多個場景中均有應用。不僅如此,這一年的 Python 在 TIOBE 程式語言排行榜中,兩度超越了 C++,湧進排行榜的前三甲。 

但當前的 Python 是否真的如此完美?

作者 | Daniel Kats
譯者 | 彎月
出品 | CSDN(ID:CSDNnews)

我剛剛從本月早些時候在 PyCon Canada 上演講的興奮中平靜下來。在會議上我見到了許多聰明的人,似乎每個人都在談論著同樣的痛點和希望。在這篇文章中,我將總結當前最為流行的程式語言 Python 的趨勢,以及所面臨的現狀。

我喜歡 Python,且在個人專案和專業專案上使用 Python 也將近 10 年了。我的工作一半是資料分析,另一半是快速原型建立,所以 Python 是個絕佳的工具。Python 本身最大的優點就是它有大量的庫,可以用來幹任何事情:機器學習、資料探索、可復現的研究、視覺化、雲功能、Web API、以及其他所有你能想到的東西。

我離不開 Python 的原因之一就是 Python 的社群非常好,在 StackOverflow 和 GitHub 上與他人交流是一件非常愉快的事情。2015 年,我的一個朋友在我們學校組織 PyCon Canada,拉著我去做志願者。我發現社群非常友好,也非常有創造力。今年,我覺得我應該做一些回饋,在我的家鄉多倫多舉行的 PyCon 上做一次演講。短短三年內社群成長了很多,我對此感到十分震驚。

和以前一樣,我發現社群裡到處都是聰明又富有創造力的人。一個例子就是在這次演講中,有一位嘉賓分享了:用 Python 發現哈利波特中的性別偏差”,不管你覺得這個題目如何,但確實是個非常抓人眼球又非常好笑的題目。

但是,像任何工程一樣,Python 依然在建設中。我們對於 Python 語言的感受甚至不同於五年前,因此當時一些看似不熟悉的事情,今天不僅成為了可能,甚至成為了理所當然。這篇文章將闡述一些 Python 的發展方向,以及我對於它們成長的看法。

一、優點

2018 年的 Python 世界中出現了許多新東西,一些甚至度過了成長的煩惱期。下面是我個人喜愛的一些:

JupyterLab

Jupyter Notebook 是一個可以執行 Python(及其他語言)的 Web 應用程式,並能立即以嵌入的方式檢視執行結果,包括圖表、格式化後的表格以及 Markdown 各式的文字等。它還會自動儲存中間結果(像 REPL 一樣),可以匯出成多種格式,還有上百種其他功能。

Jupyter Notebook 在社群中被廣泛使用,特別是在研究和科學領域。Jupyter 團隊毫無爭議地贏得了 2017 年的 ACM 軟體系統獎。

JupyterLab 是在傳統 Jupyter notebook 上進行了改進。它包含一些非常好的功能,如單元格拖拽、嵌入式檢視資料檔案(如 CSV)、標籤頁式的環境,以及一個以命令為中心的介面。當然它仍然在 beta 階段,還有一些小問題,如 Revea.js 幻燈片匯出功能,單元格摺疊功能等都不能正常使用。但整體來說,它表明一個好的工具會不斷成長並進步,以滿足使用者的複雜需求。

mypy

mypy 是一個 Python 的靜態型別檢查工具,它已經出現有一段時間了。但是,這幾年它發展得很好了,你甚至可以把它通過 git hooks 或其他 CI 流程來整合到產品的專案中。我發現它對所有程式碼都非常有用,甚至能在我編寫單元測試之前捕獲到我的各種錯誤。當然它也不是沒有陷阱。許多情況下你得寫一些看似多餘的註釋:

__init__(self, *args) -> None

其他行為我也認為有些奇怪。而且,許多常用的模組都沒有型別檔案,如:

  • flask:https://github.com/python/typeshed/issues/28

  • msgpack:https://github.com/msgpack/msgpack-python

  • coloredlogs:https://github.com/xolox/python-coloredlogs

  • flask-restplus:https://github.com/noirbizarre/flask-restplus

  • sqlalchemy:https://github.com/zzzeek/sqlalchemy

  • nacl:https://github.com/pyca/pynacl

因此這些庫會阻礙你將 mypy 整合到你的 CI 系統中,除非你做出大量配置。--ignore-missing-imports 選項基本上是必須的。我希望以後為各種庫的模組提供型別檔案能成為社群的基本標準。

pipfile 和 pipenv

pipfile 讓我感到非常激動!pipfile 是 PEP508 的一個實現,它的動機是用依賴管理系統替換 requirements.txt。

最原始的動機就是,使用 pip 進行的依賴管理與其他 Rust、Javascript 等語言中類似的系統比起來太落後了。雖然 pip / requirements.txt 的缺點眾所周知的,但我見過總結得最全面的就是這篇文章(https://www.kennethreitz.org/essays/a-better-pip-workflow)。我建議閱讀一下全文,不過大致內容如下:

requirements.txt 沒有標準:它應該列出所有直接和間接的依賴,或者只是直接的依賴?是否應該包括固定的版本號?另外,開發時所需的依賴也非常依賴個人喜好。不同的開發團隊會使用不同的規則,會讓構建的重現成問題。

為了保證依賴列表最新,就要在 pip install $package 之後立即執行 pip freeze > requirements.txt,這個流程非常難用,而且有許多問題。

依賴管理系統包含三個工具和標準(virtualenv,pip和requirements.txt),它們之間並沒有明確的互操作性。它們的存在都是為了完成單一的任務,那麼為什麼沒有單一的工具來做這件事呢?

使用 pipenv 吧。

pipenv 會自動建立 virtualenv,安裝並管理該 virtualenv 下的所有依賴,並自動保持 pipfile 最新。

儘管這個想法很好,但使用起來很麻煩。我在實際使用中遇到了許多問題,經常得回到前一種方式,比如顯式地使用 virtualenv。我還發現 locking 操作非常慢(部分源自 setup.py 的標準,也是工具鏈生態標準中的許多問題之一)。

f-strings

f-strings 太棒了!許多人都寫過 f-strings 的好處,包括它們自然的語法和帶來的效能提升。我沒有必要重複這些點,我只想說,這個功能非常棒,從它一出現我就一直在用。

f-strings 帶來的一個有點討厭的地方就是書寫 print 語句和 logging 語句之間的區別。logging 模組很好,而且預設情況下,如果日誌訊息被關閉,那麼格式化就不會進行。所以你可以寫:

x = 3

logging.debug(‘x=%d’, x)

如果日誌級別設定為 DEBUG,就會輸出 x=3,但如果日誌級別更高,就不會進行字串插值。這是因為 logging.debug 是函式,而字串作為引數傳遞。可以在這篇“非常容易理解的 C 原始碼”文章(https://github.com/python/cpython/blob/master/Lib/logging/__init__.py#L1419)中看到它的工作原理。但是,如果這樣寫,這個功能就消失了:

x = 3

logging.debug(f’x={x}’)

不管日誌級別是什麼,字串插值必然會執行。從語言層面來看這是合理的,但實際的結果卻讓人感到不安。除錯時我會首先使用 print 語句,如果一切看起來正常,我就會將 print 轉成 logging 語句。所以每個 print 語句都需要手動改寫,以便匹配不同型別的字串插值。我不知道應該如何解決這個問題,但我想指出這個問題,因為別人沒說過。

二、缺點

像許多與 Python 一樣老的專案一樣(Python 都和我一樣老了),一些模組和思想也上了年紀。這不是吐槽大會,我只是想說 Python 的社群可以做得更好。

tox

Tox 依然是 Python 世界中最好的測試執行器,而且它也非常糟糕。不僅是因為 tox.ini 的語法很不直觀,工具本身也非常慢。當然這並不是 tox 自己的錯誤,而是整個 setup.py 系統就有設計缺陷。因為這些檔案定義了包之間的依賴,而它們執行程式碼查詢依賴繼承關係就非常慢。這導致一系列工具都很慢。我相信 2019 年我們的社群應該嘗試解決這個問題。

此外,它依然不支援 pipfile,讓它變得更慢。像許多東西一樣,並不是說它本身好壞,而更大程度上取決於它周圍工具的好壞。

型別標註只能用於工具

引用自 PEP0484:

使用型別提示進行效能優化作為讀者練習。

考慮到該 PEP 出現時 Python 的狀態,這一點也是可以理解的,但現在應該更進一步了。我們已經成功地轉移到了 Python3,360 個 PyPi 上下載次數最多的包中有 359 個都相容 Python3。型別提示深受社群歡迎。更進一步,Python  的型別提示應該帶來更多好處,如型別優化、自動執行時型別斷言等。我發現執行時型別斷言非常有用(特別是在函式庫中),但手工編寫非常麻煩。再加上型別提示,維護多個型別系統就變得特別麻煩。

就像其他提到的那樣,Python 4 很可能會把 JIT 當做最優先的功能。似乎這是個給型別標註進行效能優化的好地方。

變數可修改性

對於現在的 Python 我最大的不滿就是它沒有 const 或類似的東西。在我犯過的所有編碼錯誤中,90% 都是型別相關的錯誤(現在可以通過 mypy 捕獲大部分),或是以為自己建立了新變數,實際上卻錯誤地使用了同一個函式中定義過的變數。我知道有些包能實現這一點,但我希望 Python 自身能支援 const。

nbconvert

nbconvet 專案非常贊。它可以將 Jupyter notebook 轉換成其他各種格式,包括 PDF、Reveal.js 幻燈片,或者可執行指令碼。在過去幾個月內我經常使用後兩者,它們真的改變了我的工作流程。我可以把一切都放在一個 notebook 中,最後再將其轉換成幻燈片在每週會議上把我的進度演示給同事。類似地我也可以在 notebook 中規劃一個想法,然後只需最小的代價將其轉換成指令碼並用在產品中。

當然這只是想法。現實是,任何大小的 notebook 轉換成指令碼都需要大量手工操作才能成功轉換,有時還不如手動複製貼上。我聽說許多公司建立了 nbconvert 的 wrapper 使它更容易使用。我希望這些人能開源,這樣就能解決我的痛苦了。

三、結論

許多優秀的人鼓勵我寫這篇文章,我感謝他們的反饋和支援。如果你有不同意見,歡迎留言分享你的看法。

原文:https://medium.com/@dbkats/state-of-python-in-2018-68fe478f8bb6

本文為 CSDN 翻譯,如需轉載,請註明來源出處。