為什么有些高級開發(fā)人員不喜歡Python
本文轉(zhuǎn)載自公眾號“讀芯術(shù)”(ID:AI_Discovery)。
許多高級開發(fā)人員表示,他們發(fā)現(xiàn)使用動態(tài)類型的語言令人頭疼。下面的響應(yīng)收集了大部分拍手。
| “對不起,什么?動態(tài)類型的語言比靜態(tài)類型的語言容易出錯嗎?抱歉,但是不是我21年的軟件開發(fā)生涯。”
—拉斯姆斯·舒爾茨(Rasmus Schultz) |
遵循此答案,我決定匯總使高級開發(fā)人員避開動態(tài)鍵入語言的主要原因,并在此處列出這些理由以消除誤解。
為了更好地解決此問題,由于Python的迅猛發(fā)展,我們將以Python作為動態(tài)類型語言的示例。
動態(tài)類型
在這種情況下鍵入與擊鍵無關(guān)。這個詞是從數(shù)據(jù)類型派生的。
在編程方面,許多類型的類(例如強類型和鴨子類型)都可以發(fā)揮作用。但是,我們將自己限制為最常見的幾個:
- 動態(tài)類型
- 靜態(tài)類型
動態(tài)類型是在運行時標(biāo)記類型錯誤的情況。也就是說,也不必像Python,Ruby和JavaScript那樣顯式聲明數(shù)據(jù)類型。
與動態(tài)類型相反,靜態(tài)類型是在編譯期間報告類型錯誤和顯式聲明數(shù)據(jù)類型的報告。C,C ++和Java就是這種情況。
一般來說,關(guān)于Python和編程語言的有趣之處在于,它們的某些優(yōu)點還是缺點。
動態(tài)類型設(shè)置為通過隱式數(shù)據(jù)類型聲明刪除一些代碼行來簡化編碼過程。但是,此功能有很大的陷阱。
為了讓您當(dāng)場,請考慮以下Python代碼示例:
- max_number = 12
- my_list = []
- for i in range(1, 5):
- max_numbre = 2 * (max_number * i)
- my_list.append(max_number)
- print(my_list)
輸出:
- [12, 12, 12, 12]
在上面的示例中,我們要對變量max_number執(zhí)行計算并將結(jié)果存儲在列表中。但是,我們可以看到這一切都沒有發(fā)生,并且結(jié)果是錯誤的。這是因為在for循環(huán)中,我們拼錯了max_number,導(dǎo)致創(chuàng)建了另一個名為max_numbre的變量。
任何人都可能犯此類錯誤,尤其是在工作壓力很大的人身上。
現(xiàn)在說您正在編寫大量代碼。您將需要更加注意下一步您的手指應(yīng)點擊哪些鍵。否則,跟蹤代碼中的錯誤可能會成為噩夢,從而導(dǎo)致可維護性問題。
但是,在像C ++這樣的靜態(tài)類型語言中,必須在使用前聲明變量。而且您一定要進(jìn)行執(zhí)行前分析,以確保您的變量類型協(xié)調(diào)一致。由于可以更好地控制變量,因此最終可以提高安全性。
靜態(tài)類型的重要性的一個例子是2009年與三名Twitter開發(fā)人員的對話,討論了公司為何決定合并靜態(tài)類型的語言Scala。
全局解釋鎖
高級開發(fā)人員會對性能感到驚訝的一件事是性能。
與初級人員不同,初級人員需要處理幾行代碼,維護和編寫健壯的生產(chǎn)代碼(通常為數(shù)百行或數(shù)千行代碼),是由經(jīng)驗豐富的開發(fā)人員承擔(dān)的。因此,擁有高效的編程語言可能會變得毫無疑問。
就是說,由于全局解釋器鎖(GIL)禁止充分利用計算機的資源,因此它是編程語言(如Python和MRI Ruby)的性能瓶頸。GIL損害的資源是CPU線程。
不過,不使用GIL的編程語言會充分利用CPU的功能。因此已知它們支持并行計算。
并行計算無非就是讓所有線程同時運行。由于需要處理的天文數(shù)據(jù)數(shù)量眾多,因此這種類型的計算現(xiàn)在比以往任何時候都更加重要。
下圖是一個并行計算的示例:

> Example of all CPU threads running. Diagram created by the author in diagram.net
可以合理地假設(shè),在相同的CPU時鐘速度下,計算機擁有的線程越多,程序運行速度就越快。
但是,GIL的出現(xiàn)終結(jié)了并行計算。
GIL是一種鎖,一次僅允許一個線程使用GIL。線程的選擇遵循排隊方式。這意味著,當(dāng)具有最高優(yōu)先級的線程正在使用GIL時,其他線程將處于等待狀態(tài),直到釋放GIL。
最重要的是,用戶無法控制線程選擇。相反,操作系統(tǒng)是負(fù)責(zé)線程優(yōu)先級排序的操作系統(tǒng)。
下圖最好地說明了發(fā)生的方式:

> GIL effects on the threads. Diagram created by the author in diagram.net
為了解決此問題,許多程序員,或者至少是聰明的程序員,嘗試使用例如Python的多線程模塊在線程之間手動拆分進(jìn)程,以期獲得更好的性能。他們最終最終會獲得更差的性能。
盡管結(jié)果似乎很奇怪,但它是計算機科學(xué),而不是計算機推測。如果您對問題進(jìn)行更深入的研究,那么一切都應(yīng)該放到位。
盡管Python的核心開發(fā)團隊完全意識到了這個問題,但很難擺脫GIL,因為它是Python許多細(xì)節(jié)的骨干,例如內(nèi)存管理和C擴展(僅舉幾例)。
Python的正式作者Guido van Rossum表示,他對Python是否會支持并行計算并不充滿信心,因為這最終是該語言的設(shè)計方式。
但是,諸如C ++之類的靜態(tài)類型語言不受GIL的限制。這使得它們在比較中效率很高。
空格敏感性
使用一種會因空格錯位和缺失而標(biāo)記錯誤的編程語言,可能并不是每個人的功勞。這些空格是空格,制表符,換行,返回或換頁。例如,與C不同,Python確實對空格敏感。
我們將通過以下C和Python代碼之間的比較來證明這一點。
Python版本:
- i = 50
- if i % 2 == 0:
- print("inside if statement") print("i is even")
輸出:
- print("inside if statement") print("i is even")
- ^
- SyntaxError: invalid syntax
C版:
- #include<stdio.h>int main(void)
- {int i = 50;if (i % 2 == 0)
- {printf("inside if statement\n");printf("i is even\n");}}
輸出:
- ~/ $ ./test1
- inside if statement
- i is even
與抵制混亂的代碼結(jié)構(gòu)并最終得到正確輸出的C版本不同,Python生成的語法錯誤最初是由語句放置錯誤引起的。因此,有人會說Python不如C ++或原始C健壯。
具有諷刺意味的是,盡管許多專業(yè)程序員認(rèn)為空白敏感性很煩人,但許多Pythonista人士認(rèn)為處理空白問題比最后進(jìn)行列追逐要好。
最后,在處理大型代碼塊時,空格敏感性問題令人討厭。但是,如果在團隊中灌輸良好的編碼習(xí)慣,則可以輕松解決空白敏感性問題。
向后兼容
不支持向后兼容性意味著舊版本的Python代碼在新版本下可能無法工作。換句話說,絕對需要查找新版本中發(fā)生的語法更改,并相應(yīng)地重寫其代碼。
當(dāng)向后兼容性成為一個嚴(yán)重問題時,一個很好的例子是第一次從Python 2過渡到3。
Python核心開發(fā)團隊認(rèn)為,人們將Python 2代碼轉(zhuǎn)換為Python 3不會有問題。但是他們錯了。
Python的作者本人在講話時承認(rèn)了這一點:
|
“我們低估了多少人已經(jīng)編寫了大量的Python代碼,然后基本上忘記了它是如何工作的。因此,他們不是很擅長升級它。我們意識到那里存在問題。” |
關(guān)于該問題的裁決是延長了Python 2.7的壽命。
總結(jié)
編程語言一直是熱門話題,因此不能將其視為對與錯。至少有一些原因使他們偏愛另一種語言。
通常,每種通用編程語言都適合特定的人群。Python的官方作者說:
| “學(xué)習(xí)使用Python編程比學(xué)習(xí)使用Java或Swift編程容易得多。對于學(xué)習(xí)計算機科學(xué)的專業(yè)軟件開發(fā)人員來說,Java和Swift是很棒的編程語言。然后開始為一家軟件開發(fā)公司工作。但是Python可以教給初中的孩子。” |
除此之外,最理想的情況是擁有一種可以結(jié)合C ++和Python優(yōu)點的編程語言。
原文鏈接:
https://medium.com/better-programming/why-some-senior-developers-dont-like-python-974c5361fff2



























