中文字幕在线观看,亚洲а∨天堂久久精品9966,亚洲成a人片在线观看你懂的,亚洲av成人片无码网站,亚洲国产精品无码久久久五月天

Python「八宗罪」

2018-12-21    來源:raincent

容器云強(qiáng)勢(shì)上線!快速搭建集群,上萬Linux鏡像隨意使用

本文作者有一群 geek 朋友,經(jīng)常一起討論技術(shù)話題,有時(shí)候也會(huì)談到編程語言!窱 hate Python」,作者表示。他對(duì) Python 厭惡至極。即使有現(xiàn)成的 Python 代碼可用,他也寧愿用 C 語言重寫。為了系統(tǒng)地吐槽 Python,作者專門寫了這篇博客,細(xì)數(shù) Python 的「八宗罪」。

這個(gè)話題已經(jīng)在 Hacker News 上引發(fā)了熱烈的討論(評(píng)論 400+),感興趣的讀者可以去圍觀或參與一下。

Hacker News 討論:https://news.ycombinator.com/item?id=18706174

1. 版本

如果要安裝一個(gè)默認(rèn)的 Linux 操作系統(tǒng),那你很有可能需要安裝多個(gè)版本的 Python:Python2、Python3 甚至是 3.5、3.7。原因在于:Python3 無法與 Python2 完全兼容。甚至一些用小數(shù)表示的版本(如 3.5、3.7)也明顯缺乏向后的兼容性。

我完全贊成往編程語言中添加新的功能,我甚至不介意淘汰一些舊的版本。但 Python卻要分開安裝。我的 Python 3.5 代碼不適用于 Python 3.7 安裝版本,除非我特意將其導(dǎo)入 3.7。很多 Linux 開發(fā)者都覺得導(dǎo)出太麻煩,因此安裝 Ubuntu 的時(shí)候會(huì)一并安裝 Python2 和 Python3——因?yàn)橛械暮诵墓δ苄枰罢,而有的需要后者?/p>

向后兼容性的缺乏和各自為政的版本通常會(huì)為其敲響喪鐘。Commodore 創(chuàng)造了第一批家用電腦(比 IBM PC 和蘋果都要早很多)。但 Commodore PET 不能與后續(xù)的 Commodore CBM 兼容。CBM 又不與 VIC-20、Commodore-64、Amiga 等兼容。因此,你要么選擇花很多時(shí)間將代碼從一個(gè)平臺(tái)導(dǎo)到另一個(gè),要么選擇放棄這個(gè)平臺(tái)。(Commodore 今天何在?早被用戶拋棄涼涼了……)

類似地,Perl 也火過一陣。但 Perl3 與 Perl2 的很多代碼也不兼容。社區(qū)罵聲一片,于是一些好的代碼導(dǎo)了出來,其他的則被拋棄了。Perl4 也是如此。等 Perl5 出來的時(shí)候,人們干脆改用另一種更穩(wěn)定的編程語言。如今,只有一小部分人還在頻繁使用 Perl 來維持之前的項(xiàng)目。但已經(jīng)沒有人用 Perl 創(chuàng)建新的大項(xiàng)目了。

同理,Python 的每個(gè)版本也都存在谷倉(cāng)效應(yīng)。之前的版本還要留著,最終造成手里有一堆舊的無用 Python 代碼,因?yàn)榇蠹叶疾幌牖〞r(shí)間將其移到最新版上。據(jù)我所知,沒有人為 Python2 創(chuàng)建新代碼了,但我們還留著它,因?yàn)闆]有人想將所需代碼移到 Python3.x 中。Python 2.7、3.5、3.6、3.7 的文檔都還在 Python 官網(wǎng)上積極維護(hù)著,因?yàn)樗麄儫o法下決心棄用之前的代碼。Python 就像一種僵尸編程語言——已經(jīng)死掉的部分還在以行尸走肉的方式存在著。

2. 安裝

很多軟件包都可以幫你輕松地運(yùn)行 apt、yum、rpm 或其他一些安裝庫(kù),并獲得最新版本的代碼。但 Python 并非如此。如果用「apt-get install python」安裝,你都不知道自己安的是哪個(gè)版本,它可能也無法與你所需的所有代碼兼容。

因此,你要安裝你需要的那版 Python。我的其中一個(gè)項(xiàng)目用到 Python,但必須用 Python3.5。所以最后,我的電腦安裝了 Python2、Python2.6、Python3 及 Python3.5。其中兩個(gè)來自操作系統(tǒng),一個(gè)用于項(xiàng)目,另外一個(gè)服務(wù)于出于其他原因安裝的無關(guān)軟件。雖然都是 Python,但此 Python 非彼 Python。

如果你想安裝 Python 包,你應(yīng)該使用「pip」(Pip Installs Packages)。但由于系統(tǒng)上有一堆 Python,你要注意使用正確版本的 pip。否則,「pip」可能運(yùn)行「pip2」,而不是你需要的「pip3.7」。(如果名稱不存在,你需要為 pip3.7 指定明確的真實(shí)路徑)

一位隊(duì)友建議我配置自己的環(huán)境,這樣的話每種軟件都可以使用 Python3.5 的 base 環(huán)境。在我需要用 Python3.6 開展另一個(gè)項(xiàng)目之前,這種做法是非常行得通的,但是需要 Python 3.6 就得創(chuàng)建另外一個(gè)環(huán)境。兩個(gè)項(xiàng)目,兩版 Python,一點(diǎn)都不會(huì)混,真的(用生命在假笑)。

pip 安裝程序?qū)⑽募胖迷谟脩舻谋镜啬夸。安裝系統(tǒng)級(jí)的庫(kù)時(shí)不用 pip。Gawd 不允許你在運(yùn)行「sudo pip」時(shí)出錯(cuò),因?yàn)槟菚?huì)毀了你的整個(gè)電腦!運(yùn)行 sudo 可能會(huì)使一些軟件包在系統(tǒng)級(jí)別安裝,有些是為錯(cuò)誤版本的 Python 安裝的,而你的主目錄中的一些文件可能最終歸 root 所有,因此未來的非 sudo pip 安裝可能會(huì)因權(quán)限問題而失敗。不要這樣做。

這些 pip 模塊由誰來維護(hù)呢?當(dāng)然是社區(qū)。也就是說,沒有明確的所有者,也沒有強(qiáng)制性的來源鏈或責(zé)任鏈。今年早些時(shí)候,PyPI 的一個(gè)版本中發(fā)現(xiàn)了一個(gè)竊取 SSH 憑證的后門。這也是意料之中。(出于同樣的原因,我不用 Node.js 和 npm;我不信任他們的社區(qū)項(xiàng)目。)

3. 句法

我非常主張代碼的可讀性要強(qiáng)。乍一看,Python 的可讀性似乎不錯(cuò)。但當(dāng)你開始創(chuàng)建大型代碼庫(kù)的時(shí)候你就不會(huì)這么想了。

大多數(shù)編程語言使用某種符號(hào)來標(biāo)識(shí)范圍——函數(shù)的開始和結(jié)束位置、條件語句中包含的操作、變量的定義范圍等。C 語言、Java、JavaScript、Perl 和 PHP 都用 {...} 來定義范圍,Lisp 使用 (...)。Python 呢?它用空格!如果你要定義復(fù)雜代碼的范圍,你可以縮進(jìn)接下來的幾行代碼,縮進(jìn)結(jié)束時(shí),該范圍也截止。

Python 手冊(cè)說,你可以用任意數(shù)量的空格或制表符來定義范圍。但是,每次縮進(jìn)最好使用四個(gè)空格!如果你想縮進(jìn)兩次進(jìn)行嵌套,使用八個(gè)空格!Python 社區(qū)已經(jīng)對(duì)此進(jìn)行標(biāo)準(zhǔn)化,即使 Python 手冊(cè)中并沒有明文規(guī)定。這個(gè)社區(qū)就喜歡用四個(gè)空格。所以,除非你不打算將自己的代碼向任何人展示,否則的話每次縮進(jìn)最好用四個(gè)空格。

我第一次看到 Python 代碼時(shí),覺得用縮進(jìn)來定義范圍還挺好的,但這么做有一個(gè)巨大的缺陷。你可以進(jìn)行深度嵌套,但這么做使得每一行都會(huì)很長(zhǎng),導(dǎo)致不得不在文本編輯器中換行。較長(zhǎng)的函數(shù)和條件語句可能會(huì)使開始和結(jié)束范圍很難匹配。而且當(dāng)你不小心把三個(gè)空格當(dāng)成四個(gè)空格,還容易出現(xiàn)計(jì)算錯(cuò)誤,進(jìn)而花幾個(gè)小時(shí)來調(diào)試和追蹤。

對(duì)于其它語言,我已經(jīng)養(yǎng)成了調(diào)試代碼不帶任何縮進(jìn)的習(xí)慣。這樣,我可以快速瀏覽代碼,然后輕松地識(shí)別和刪除調(diào)試代碼。但 Python 呢?任何沒有適當(dāng)縮進(jìn)的代碼都會(huì)產(chǎn)生縮進(jìn)錯(cuò)誤。

4. includes

大部分編程語言都有辦法導(dǎo)入其它代碼塊。比如,C 語言用「#include」,PHP 語言可以用「include、include_once、require、require」。而 Python 用的是「import」。

Python 可以導(dǎo)入整個(gè)模塊、模塊的一部分或模塊中的特定函數(shù)。C 語言?你可以查看「/usr/include/」。Python 的話,最好用「python -v」列出所有路徑,然后從列表中搜索每個(gè)目錄和子目錄中的每個(gè)文件。我有些朋友很喜歡 Python,但我看到他們想導(dǎo)入東西時(shí),總得瀏覽標(biāo)準(zhǔn)模塊。

導(dǎo)入功能還允許用戶重命名導(dǎo)入的代碼。它們基本上定義了一個(gè)自定義的命名空間。乍一看,你會(huì)覺得挺不錯(cuò)的,但這最終會(huì)影響可讀性和長(zhǎng)期支持。重命名對(duì)于較小的腳本來說還是不錯(cuò)的,但對(duì)于長(zhǎng)期項(xiàng)目來說真的不適用。那些使用 1-2 個(gè)字母作為命名空間(比如「import numpy as n」),而且還不按約定俗成的方式來命名的,簡(jiǎn)直應(yīng)該拉出去槍斃!

這還不是最糟糕的。大部分編程語言 include 代碼的時(shí)候就只是導(dǎo)入代碼而已。如果有一個(gè)帶有構(gòu)造函數(shù)的全局對(duì)象,有些語言,如面向?qū)ο蟮?C++可能會(huì)執(zhí)行代碼。類似地,有些 PHP 代碼可能會(huì)定義全局變量,所以導(dǎo)入可以運(yùn)行代碼——但這種做法通常被認(rèn)為很糟糕。相比之下,很多 Python 模塊包含在導(dǎo)入期間運(yùn)行的初始化函數(shù)。你不知道在運(yùn)行的是什么,它要干什么,你甚至可能不會(huì)注意到。除非存在命名空間沖突,如果這樣就好玩了,你得花很多時(shí)間來尋找原因。

5. 命名法

在其它語言中,數(shù)組(array)直接稱之為'arrays',但是在 Python 中,它們被稱為 'lists'。關(guān)聯(lián)數(shù)組在某些地方被稱為 'hash' (Perl),但是 Python 將其稱為「字典」(dictionary)。Python 似乎完全按照自己的節(jié)奏來,不使用計(jì)算機(jī)科學(xué)和信息科學(xué)領(lǐng)域的常見術(shù)語。

此外,Python 庫(kù)的命名也有問題。PyPy、PyPi、NumPy、SciPy、SymPy、PyGtk、Pyglet、PyGame……(前兩個(gè)庫(kù)的發(fā)音一樣,但是它們的功能完全不同)。我理解「py」表示 Python,但是它們就不能統(tǒng)一出現(xiàn)在前面或后面嗎?

一些常見庫(kù)放棄了類似雙關(guān)語的「Py」命名約定,包括 matplotlib、nose、Pillow和 SQLAlchemy。雖然有一些命名可能暗示其目的(如 SQLAlchemy 包含 SQL,所以它可能是一個(gè) SQL 接口),但是其它的可能只是隨機(jī)的單詞。如果你不知道「BeautifulSoup」這個(gè)庫(kù)是干什么的,那么你能從命名看出來它是一個(gè) HTML/XML 解析器嗎?不過,BeautifulSoup 有很完善的文檔且易于使用,如果每一個(gè) Python 模塊都這樣,我也就不抱怨了,但是大多數(shù) Python 庫(kù)的文檔非常爛。

總的來說,我認(rèn)為 Python 是一個(gè)具有不一致命名約定的函數(shù)庫(kù)集合。我經(jīng)常抱怨開源項(xiàng)目的命名非常可怕。除非你知道這些項(xiàng)目在干什么,否則你從命名本身中什么都看不出來。除非你知道在尋找什么樣的庫(kù),不然只能通過別人偶然提及的名字或偶然的機(jī)會(huì)發(fā)現(xiàn)一些庫(kù)。大多數(shù) Python 庫(kù)加重了這種現(xiàn)象,也加重了 Python 的負(fù)面體驗(yàn)。

6. 奇怪的操作

每種語言都有自己比較奇特的操作。C 語言中使用 & 和 * 獲取地址空間和值的命名法非常奇怪。C 語言中還有用 ++ 和—實(shí)現(xiàn) increment/decrement 的捷徑。Bash 語言中,在引用特定字符(如用于正則表達(dá)式的圓括號(hào)和句號(hào))時(shí)需要一直考慮「什么時(shí)候使用轉(zhuǎn)義符 (\)」。JavaScript 兼容性有問題(并非每個(gè)瀏覽器都支持所有有用的功能)。但 Python 的奇怪操作比我見過的其他語言都多。如:

在 C 語言中,雙引號(hào)里的是字符串,單引號(hào)里的是字符。

在 PHP 和 Bash 中,兩種引號(hào)都能包含字符串。但是,雙引號(hào)里的字符串可以嵌入變量。相比之下,單引號(hào)的字符串是文字;任何嵌入的類似變量的名稱都不可擴(kuò)展。

在 JavaScript 中,單引號(hào)和雙引號(hào)沒什么區(qū)別。

在 Python 中,單引號(hào)和雙引號(hào)也沒有什么區(qū)別。但是,如果你想讓字符串跨行,就得用三重引號(hào),如"""string""" 或 '''string'''。如果你想用二進(jìn)制,那你需要優(yōu)先選擇帶有 b(b'binary')或 r(r'raw')的字符串。有時(shí)你要用 str(string) 把字符串轉(zhuǎn)換為字符串,或使用 string.encode('utf-8') 將其轉(zhuǎn)換為 utf8 格式。

如果你一開始認(rèn)為 PHP 和 JavaScript 中的=、==、===有點(diǎn)奇怪,那等你用 Python 中的引號(hào)時(shí)可能不會(huì)這么想了。

7. 通過對(duì)象 Reference 傳遞

大多數(shù)編程語言的函數(shù)參數(shù)傳遞是傳值。如果函數(shù)改變了值,結(jié)果不會(huì)傳遞回調(diào)用代碼。但正如我解釋過的,Python 偏偏要有所不同。Python 默認(rèn)使用 pass-by-object-reference 來傳遞函數(shù)參數(shù)。這意味著改變?cè)醋兞靠赡茏罱K會(huì)改變值。

這是面向程序、函數(shù)和對(duì)象的編程語言之間的最大區(qū)別。如果每個(gè)變量都由對(duì)象引用來傳遞,并且變量的任何變化都會(huì)改變所有的引用,那你可能使用的都是全局對(duì)象。通過不同的命名調(diào)用相同的對(duì)象不會(huì)改變對(duì)象,所以實(shí)際上它就是全局的。此外,正如 C 的程序員早就學(xué)到的,全局變量太惡心了,別用。

在 Python 中,你必須通過值來傳遞變量,例如「a=b」只是給相同的對(duì)象空間分配了另一個(gè)命名,但并沒有復(fù)制 b 的值給 a。如果你真的想要復(fù)制 b 的值,你需要使用一個(gè) copy 函數(shù),通常是「a=b.copy()"的形式。然而,注意我說的是「通常」。不是所有數(shù)據(jù)類型都有一個(gè)「copy」原型,或者 copy 函數(shù)可能是不完整的。在這種情況下,你可以使用單獨(dú)的「copy」庫(kù):"a=copy.deepcopy(b)"。

8. 本地命名

用所用的庫(kù)或函數(shù)的名字來命名程序是常見的編程技巧。例如,如果我用一個(gè)叫做「libscreencapture.so」的 C 庫(kù)來測(cè)試一個(gè)截屏程序,我會(huì)將該程序命名為「screencapture.c」并編譯為「screencapture.exe」。

gcc -o screencapture.exe screencapture.c -lscreencapture

在 C、Java、JavaScript、Perl、PHP 等語言中,這通常很有效,因?yàn)檫@些語言可以輕易地辨別本地程序和資源庫(kù),它們有不同的路徑。但 Python 呢?還是算了吧,千萬別這樣做。為什么?Python 會(huì)假定你首先要導(dǎo)入本地代碼。如果我有一個(gè)名為「screencapture.py」的程序使用了「import screencapture」,那么它將導(dǎo)入自己而不是系統(tǒng)庫(kù)。至少,你應(yīng)該調(diào)用本地程序「myscreencapture.py」吧。

并非一無是處

Python 是一門非常流行的編程語言,有很多粉絲。甚至我的很多朋友都很喜歡 Python。多年來,我和他們討論過這些問題,每次他們都點(diǎn)頭表示同意。他們并不反對(duì) Python 存在這些問題,只是認(rèn)為這不足以澆滅他們對(duì)這種語言的熱情。

我的朋友經(jīng)常提到那些非常酷的 Python 庫(kù)。我同意一些庫(kù)非常有用。例如,BeautifulSoup 是我用過最好的 HTML 解析器之一,NumPy 使多維數(shù)組和復(fù)雜的數(shù)學(xué)更容易實(shí)現(xiàn),而 TensorFlow 對(duì)于機(jī)器學(xué)習(xí)非常有用。但是,我不會(huì)因?yàn)橄矚g TensorFlow 或 SciPy 而用 Python 創(chuàng)建單片程序。我不打算為了這些「蠅頭小利」而放棄可讀性和可維護(hù)性,這不值得。

通常當(dāng)我寫一篇關(guān)于某個(gè)主題的批評(píng)時(shí),我也會(huì)嘗試寫一些積極的東西。但我沒辦法列出關(guān)于 Python 的好的方面,因?yàn)槲艺娴恼J(rèn)為 Python 很糟糕。

原文地址:https://www.hackerfactor.com/blog/index.php?/archives/825-8-Reasons-Python-Sucks.html

標(biāo)簽: isp linux 代碼 腳本 開發(fā)者 權(quán)限 搜索

版權(quán)申明:本站文章部分自網(wǎng)絡(luò),如有侵權(quán),請(qǐng)聯(lián)系:west999com@outlook.com
特別注意:本站所有轉(zhuǎn)載文章言論不代表本站觀點(diǎn)!
本站所提供的圖片等素材,版權(quán)歸原作者所有,如需使用,請(qǐng)與原作者聯(lián)系。

上一篇:斯坦福大學(xué)CS 230的深度學(xué)習(xí)秘籍—帶你速覽深度學(xué)習(xí)核心知識(shí)

下一篇:清華北大留不住,高中畢業(yè)去美國(guó)讀AI本科值不值?