聊聊我對python的感覺

工做中主要是在寫python2,把python做爲用戶邏輯的載體的,通常是C++寫好底層,導出成python模塊使用,或者是可執行程序帶起來一個python虛擬機,把函數注入進去,而後加載python代碼執行。我接觸的這部分python,沒有太多的框架,幾乎不使用基本數據結構以外的標準庫,由於不少東西都是C++封裝好給python的,性能比純python好不少。所以下面的文字也主要圍繞着我使用的這個python的子集展開,若是有所誤差,那也是沒法避免的。python

python的一些優勢

hook一切的能力

python的裝飾器提供了一種在定義處直接修改被定義的對象的能力,有點相似清潔宏。宏這種東西,目的就是對語言的語法樹作變換,生成被調整過的語法樹結構,來達到抽象某些東西的意義。然而大部分加宏,尤爲是清潔宏的語言,都不可避免的要考慮一個問題,就是如何表示語法樹和語法樹的變換。Lisp系由於自己代碼就是數據,因此語法樹,代碼,變換都是S-expr;rust則是發明了另外一套語法來作這一件事情;還在proposal階段的C++ reflection,不只要發明語法,還要發明對應的庫和namespace,甚至還要和constexpr之類的東西耦合,這就很醜,並且又很大地增長了語言的複雜度。不噴C++了,python的裝飾器很巧妙的複用了python語法,經過放棄一些變換的自由度的方式(裝飾器只能以函數/類爲單位進行變換)實現了較爲舒服的宏。數組

另外一個要說的就是metaclass,metaclass用來hook類型的建立,能夠用來作一些在類型建立時對類型進行調整的工做,好比增減類變量,修改基類,註冊一些東西,變換一下函數等等。數據結構

最後就是屬性索引器__get__和__set__,我曾經在看到他們以後忽然意識到,這就是C#的DependencyProperty須要的東西,不經過用戶編寫代碼,來達到hook一個屬性的讀取和寫入的能力。寫過WPF的同窗都知道,WPF裏面有一套很複雜的DependencyProperty/Object系統,其實說白了就是須要hook屬性更改,用來作數據綁定之類的東西,寫起來很麻煩,VS也專門提供了插入dependency property定義的boilerplate的功能。python這個屬性索引器設計就很好的解決了這個問題,至少讓代碼寫起來沒有那麼多廢話了。框架

有人可能以爲我用C++和C#跟python對比不合適,的確,這些語言的主戰場是大型系統,高性能,硬件抽象,的確不適合用來實現過於靈活的東西。函數

不吝於用開洞的方法來解決問題

python有不少魔術方法,並且隨着語言的進化,還在加入更多的魔術方法。對象構造走魔術方法,運算符重載走魔術方法,上面說的hook屬性索引器也是魔術方法,甚至檢查一個類是否是另外一個的基類,也能夠走魔術方法。當語言層面原生爲你提供不少hook的時候,尤爲是須要靈活性的動態語言,他的靈活性就真的有了。反觀C++一直在吹噓咱們能夠用抽象來實現一切東西,而後寫出來的東西都是一坨一坨的模板,而後initializer_list,structured binding,attribute仍是忍不住開了洞。C#這樣語法還算很優雅的語言,也須要一堆boilerplate來作dependency property。固然他們都是靜態語言,主戰場是性能,原本就不該該和動態語言相比較。性能

另外一個要說的就是__getitem__和__setitem__,python的obj[key]和obj[key]=value走了兩個不一樣的方法,這樣就很棒地繞開了key不存在時究竟是要添加,仍是丟異常的問題。由於分開了讀取和寫入,obj[key],不存在丟異常,obj[key]=value,不存在就添加,和C#/C++的Dictionary/map設計相比好了很多,這倆一個不存在都丟異常,一個不存在都添加。優化

與C++雜亂的開洞相比,python的洞基本都開在魔術方法上,位置相對比較統一。spa

python的垃圾之處

智障縮進/換行語法

強制縮進,換行,python是惟一一個lambda會下降代碼可讀性的語言。就沒據說過其餘哪一個語言的lambda會讓代碼可讀性變差的設計

強行換行用\,尤爲是當if條件稍微長一點的時候,你不想用\,把if拆開,就得縮進好幾個tab,你用\換行,看着就跟C++寫了一坨宏似的對象

基本控制流太少

雖然傳統的for、do-while均可以變換成while來作,可是while True: if xxx break很醜哎,加個do-while又不會懷孕

雖然switch能夠用dict+lambda作,但lambda都那麼醜了,我又不想白白產生一個構造dict的overhead,只能寫一坨if else

真的慢,沒有jit,沒有內聯優化,沒有逃逸分析,對象全都開在堆上,引用計數+mark sweep也慢,處理個數組能比C++慢兩個數量級,小函數調用特別傷。

相關文章
相關標籤/搜索