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

對比了Python、Go和Rust之后,他得出了這個結(jié)論

2019-08-08    來源:raincent

容器云強勢上線!快速搭建集群,上萬Linux鏡像隨意使用

 本文主要是從 Python 開發(fā)者的角度基于開發(fā)工效學對這三種語言進行的一個比較,你可以跳過討論部分,直接查看代碼示例、性能比較(如果你想要一些硬數(shù)據(jù))、主要結(jié)論或 Python 、 Go 和 Rust 的 diffimg 實現(xiàn)。

幾年前,我負責重寫一個圖像處理服務(wù)。為了弄清楚對于給定的圖像和一個或多個轉(zhuǎn)換(調(diào)整大小、圓形裁剪、修改格式等),我的新服務(wù)創(chuàng)建的輸出是否和舊服務(wù)一致,我必須自己檢查圖像。顯然,我需要自動化,但我找不到一個現(xiàn)有的 Python 庫可以告訴我,這兩張圖片在像素級上有什么不同,因此有了 diffimg ,它可以給你一個差異比 / 百分比,或生成差異圖像(檢出 readme,里面有一個例子)。

我最初是用 Python 實現(xiàn)的(我最熟悉的語言),主要部分使用了 Pillow 。它可以用作庫或命令行工具。程序的基本部分非常小,只有幾十行,這要感謝Pillow。構(gòu)建這個工具并不費力( xkcd 是對的,幾乎所有東西都有一個 Python 模塊),但它至少對于除我自己之外的幾十人是有用的。

幾個月前,我加入了一家公司,他們有幾個服務(wù)是用 Go 編寫的,我需要快速上手這門語言。編寫 diffimg-go 看起來很有趣,甚至可能是一種有用的方法。這里有一些來自經(jīng)驗的興趣點,以及一些在工作中使用它的興趣點。

對比 Python 和 Go

(代碼: diffimg (Python)和 diffimg-go )

標準庫:Go 有一個相當不錯的 image 標準庫模塊,以及命令行 flag 解析庫。我不需要尋找任何外部依賴;diffimg-go 實現(xiàn)沒有依賴,而 Python 實現(xiàn)使用了相當重量級的第三方模塊(諷刺的是)Pillow。Go 的標準庫更有條理,而且經(jīng)過深思熟慮,而 Python 的會逐步發(fā)展,它們是多年來由許多作者創(chuàng)建的,有許多不同的約定。Go 標準庫的一致性使開發(fā)者更易于預測任何給定的模塊將如何發(fā)揮作用,而且源代碼有非常好的文檔記錄。

使用標準 image 庫的一個缺點是它不自動檢測圖像是否有一個 alpha 通道;所有圖像類型的像素值都有四個通道(RGBA)。因此,diffimg-go 實現(xiàn)要求用戶指明是否要使用 alpha 通道。這個小小的不便不值得找第三方庫來修復。

一個很大的好處是,標準庫中有足夠的內(nèi)容,你不需要像 Django 這樣的 Web 框架。用 Go 有可能在沒有任何依賴關(guān)系的情況下建立一個真正可用的 Web 服務(wù)。Python 號稱“自帶電池(batteries-included)”,但在我看來,Go 做得更好。

靜態(tài)類型系統(tǒng):我過去使用靜態(tài)類型語言,但我過去幾年一直在使用 Python 編程。體驗起初有點煩人,感覺它好像只是減慢了我的速度,它迫使我過度明確,即使我偶爾錯了,Python 也會讓我做我想做的。有點像你給人發(fā)指令而對方總是打斷你讓你闡明你是什么意思,而有的人則總是點頭,看上去已經(jīng)理解你,但是你并不確定他們是否已經(jīng)全部了解。它將大大減少與類型相關(guān)的 Bug,但是我發(fā)現(xiàn),我仍然需要花幾乎相同的時間編寫測試。

Go 的一個常見缺點是它沒有用戶可實現(xiàn)的泛型類型。雖然這不是一個構(gòu)建大型可擴展應(yīng)用程序的必備特性,但它肯定會減緩開發(fā)速度。雖然已經(jīng)有替代模式建議,但是它們中沒有一個和真正的泛型類型一樣有效。

靜態(tài)類型系統(tǒng)的一個優(yōu)點是,可以更簡單快速地閱讀不熟悉的代碼庫。用好類型可以帶來許多動態(tài)類型系統(tǒng)中會丟失的額外信息。

接口和結(jié)構(gòu):Go 使用接口和結(jié)構(gòu),而 Python 使用類。在我看來,這可能是最有趣的區(qū)別,因為它迫使我區(qū)分定義行為的類型和保存信息的類型這兩個概念。Python 和其他傳統(tǒng)的面向?qū)ο蟮恼Z言都鼓勵你將它們混在一起,但這兩種范式各有利弊:

Go 強烈建議組合而不是繼承。雖然它通過嵌入繼承,不用類,但其數(shù)據(jù)和方法不是那么容易傳遞。通常,我認為組合是更好的默認模式,但我不是一個絕對主義者,在某些情況下繼承更合適,所以我不喜歡語言幫我作出這個決定。

接口實現(xiàn)的分離意味著,如果有許多類型彼此相似,你就需要多次編寫類似的代碼。由于缺少泛型類型,在 Go 中,有些情況下我無法重用代碼,不過在 Python 中可以。

然而,由于 Go 是靜態(tài)類型的,當你編寫的代碼會導致運行時錯誤時,編譯器 / 源碼分析器(linter)會告訴你。Python 源碼分析器也可以有一點這樣的功能。但在 Python 中,當你試圖訪問一個可能不存在的方法或?qū)傩詴r,由于語言的動態(tài)性,Python 源碼分析器無法確切地知道什么方法 / 屬性存在,直到運行時。靜態(tài)定義的接口和結(jié)構(gòu)是唯一在編譯時和開發(fā)過程中知道什么可用的方法,這使得編譯時報錯的 Go 比運行時報錯的 Python 更可靠。

沒有可選參數(shù):Go 只有可變函數(shù),類似于 Python 的關(guān)鍵字參數(shù),但不那么有用,因為參數(shù)需要是相同的類型。我發(fā)現(xiàn)關(guān)鍵字參數(shù)是我真正懷念的特性,這主要是你可以把任何類型的一個 kwarg 扔給任何需要它的函數(shù),而無需重寫它的每一個調(diào)用,這讓重構(gòu)簡單了許多。我在工作中經(jīng)常使用這個特性,它為我節(jié)省了很多時間。由于沒有該特性,這使得我在處理是否應(yīng)該基于命令行標志創(chuàng)建差異圖像時顯得有些笨拙。

冗長:Go 有點冗長(盡管不是像 Java 那么冗長)。這部分是因為其類型系統(tǒng)沒有泛型,但主要是因為語言本身很小,沒有提供很多特性(你只有一種循環(huán)結(jié)構(gòu)可以使用!)。我懷念Python 的列表推導式(list comprehensions)和其他函數(shù)式編程特性。如果你熟悉Python,你一兩天就可以學完 Tour of Go ,然后你就了解了整個語言。

錯誤處理:Python 有異常,而 Go 在可能出錯的地方通過從函數(shù)返回元組 value, error 來傳播錯誤。Python 允許你在調(diào)用棧中的任何位置捕獲錯誤,而不需要你一次又一次地手動將錯誤傳遞回去。這又使得代碼簡潔,而不像 Go 那樣被其臭名昭著的 if err != nil 模式搞得雜亂無章,不過你需要弄清楚函數(shù)及其內(nèi)部的所有調(diào)用可能拋出的異常(使用 except Exception: 通常是一種糟糕的變通方案)。良好的文檔注釋和測試可以提供幫助,你在使用其中任何一種語言編程時都應(yīng)該添加。Go 的系統(tǒng)絕對更安全。如果你忽視了 err 值,你還是可以搬起石頭砸自己的腳,但該系統(tǒng)使糟糕的主意變得更明顯。

第三方模塊:在 Go 模塊出現(xiàn)之前,Go 的包管理器會把所有下載的包扔到 GOPATH/src目錄下,而不是項目的目錄(像大多數(shù)其他語言)。GOPATH/src目錄下,而不是項目的目錄(像大多數(shù)其他語言)。GOPATH 下這些模塊的路徑也會從托管包的 URL 構(gòu)建,所以你的 import 語句將是類似 import " github.com/someuser/somepackage " 這個樣子。在幾乎所有 Go 代碼庫的源代碼中嵌入 github.com 似乎是一個奇怪的選擇。在任何情況下,Go 允許以傳統(tǒng)的方式做事,但 Go 模塊仍然是個很新的特性,所以在一段時間內(nèi),在缺少管理的 Go 代碼庫中,這種奇怪的行為仍將很常見。

異步性:Goroutines 是啟動異步任務(wù)的一種非常方便的方法。在 async/await 之前,Python 的異步解決方案有點令人沮喪。遺憾的是,我沒有用 Python 或 Go 編寫很多真實的異步代碼,而 diffimg 的簡單性似乎并不適合說明異步性的額外開銷,所以我沒有太多要說的,雖然我確實喜歡使用 Go 的 channels 來處理多個異步任務(wù)。我的理解是,對于性能,Go 仍然占了上風了,因為 goroutine 可以充分利用多處理器并發(fā),而 Python 的基本 async/await 仍局限于一個處理器,所以主要用于 I / O 密集型任務(wù)。

調(diào)試:Python 勝出。pdb(以及像 ipdb 這樣更復雜的選項)非常靈活,一旦你進入 REPL,你可以編寫任何你想要的代碼。 Delve 是一個很好的調(diào)試器,但和直接放入解釋器不一樣,語言的全部功能都唾手可得。

Go 總結(jié)

我對 Go 最初的印象是,由于它的抽象能力(有意為之)有限,所以它不像 Python 那樣有趣。Python 有更多的特性,因此有更多的方法來做一些事情,找到最快、最易讀或“最聰明”的解決方案可能會很有趣。Go 會積極地阻止你變得“聰明”。我認為,Go 的優(yōu)勢在于它并不聰明。

它的極簡主義和缺乏自由限制了單個開發(fā)人員實現(xiàn)一個想法。然而,當項目擴展到幾十個或幾百個開發(fā)人員時,這個弱點變成了它的力量——因為每個人都使用同樣的語言特性小工具集,更容易統(tǒng)一,因此可以被他人理解。使用 Go 仍有可能編寫糟糕的代碼,但與那些更“強大”的語言相比,它讓你更難創(chuàng)造怪物。

使用一段時間后,我理解了為什么像谷歌這樣的公司想要一門這樣的語言。新工程師不斷地加入到大量代碼庫的開發(fā),在更復雜 / 更強大的語言中,在最后期限的壓力下,引入復雜性的速度比它被消除的速度更快。防止這種情況發(fā)生的最好方法是使用一種更不容易產(chǎn)生復雜性的語言。

所以說,我很高興工作在一個大型應(yīng)用程序上下文中的 Go 代碼庫上,有一個多樣化和不斷增長的團隊。事實上,我認為我更喜歡它。我只是不想把它用于我自己的個人項目。

進入 Rust

幾周前,我決定嘗試學習 Rust。我之前曾試圖這樣做,但發(fā)現(xiàn)類型系統(tǒng)和借用檢查(borrow checker)讓人困惑,沒有足夠的背景信息,我不知道為什么要把所有這些限制強加給我,對于我想做的任務(wù)來說大而笨重。然而,自那時以來,我對程序執(zhí)行時內(nèi)存中發(fā)生了什么有了更多的了解。我從這本書開始,而不是試圖一頭扎進去。這有很大的幫助,這份介紹比我見過的任何編程語言的介紹都要好。

在我讀過這本書的前十幾章之后,我覺得自己有足夠的信心嘗試 diffimg 的另一個實現(xiàn)(這時,我覺得我的 Rust 經(jīng)驗與我寫 diffimg-go 時的 Go 經(jīng)驗一樣多)。這比我用 Go 實現(xiàn)的時間要長,而后者比用 Python 需要的時間更長。我認為,即使考慮到我對 Python 更加熟悉,這也是對的——兩種語言都有更多的東西要寫。

在編寫 diffimg-rs 時,我注意到一些事情。

類型系統(tǒng):現(xiàn)在,我已經(jīng)習慣 Go 中更基本的靜態(tài)類型系統(tǒng)了,但 Rust 更強大(也更復雜)。有了 Go 中接口和結(jié)構(gòu)的基礎(chǔ)(它們都簡單得多),泛型類型、枚舉類型、traits、引用類型、生命周期就是全部我要額外學習的概念了。此外,Rust 使用其類型系統(tǒng)實現(xiàn)其它語言不使用類型系統(tǒng)實現(xiàn)的特性(如 Result ,我很快會介紹)。幸運的是,編譯器 / 源碼解析器非常有幫助,它可以告訴你你做錯了什么,甚至經(jīng)常告訴你如何解決這個問題。盡管如此,這比我學習 Go 的類型系統(tǒng)所用的時間要多得多,我還沒有適應(yīng)它的所有特性。

有一個地方,因為類型系統(tǒng),我正在使用的圖像庫的實現(xiàn)會導致令人不快的代碼重復量。我最終只要匹配兩個最重要的枚舉類型,但匹配其他類型會導致另外半打左右?guī)缀跸嗤拇a行。在這個規(guī)模上,這不是一個問題,但它使我生氣。也許這里使用宏是個不錯的主意,我仍然需要試驗。

let mut diff = match image1.color() {
image::ColorType::RGB(_) => image::DynamicImage::new_rgb8(w, h),
image::ColorType::RGBA(_) => image::DynamicImage::new_rgba8(w, h),
// 繼續(xù)匹配所有 7 種類型?
_ => return Err(
format!("color mode {:?} not yet supported", image1.color())
),
};

手動內(nèi)存管理:Python 和 Go 會幫你撿垃圾。C 允許你亂丟垃圾,但當它踩到你丟的香蕉皮時,它會大發(fā)脾氣。Rust 會拍你一下,并要求你自己清理干凈。這會刺痛我,甚至超過了從動態(tài)類型語言遷移到靜態(tài)類型語言,因為我被寵壞了,通常都是由語言跟在我后面撿。此外,編譯器會設(shè)法盡可能地幫助你,但你仍然需要大量的學習才能理解到底發(fā)生了什么。

直接訪問內(nèi)存(以及 Rust 的函數(shù)式編程特性)的一個好處是,它簡化了差異比的計算,因為我可以簡單地映射原始字節(jié)數(shù)組,而不必按坐標索引每個像素。

函數(shù)式特性:Rust 強烈鼓勵函數(shù)式的方法:它有 FP 友好的類型系統(tǒng)(類似 Haskell)、不可變類型、閉包,迭代器,模式匹配等,但也允許命令式代碼。它類似于編寫 OCaml(有趣的是,最初的 Rust 編譯器是用 OCaml 編寫的)。因此,對于這門與 C 競爭的語言,代碼比你想象得更簡潔。

錯誤處理:不同于 Python 使用的異常模型,也不同于 Go 異常處理時返回的元組,Rust 利用枚舉類型:Result 返回 Ok(value) 或 Err(error)。這和 Go 的方式更接近,但更明確一些,而且利用了類型系統(tǒng)。還有一個語法糖用于檢查語句中的 Err 并提前返回:? 操作符(在我看來,Go 可以用類似這樣的東西)。

異步性:Rust 的 async/await 還沒有完全準備好,但最終語法最近已經(jīng)達成一致。Rust 標準庫中也有一些基本的線程特性,看上去比 Python 的更容易使用,但我沒有花太多的時間了解它。Go 似乎仍然有最好的特性。

工具:rustup 和 cargo 分別是非常優(yōu)秀的語言版本管理器和包 / 模塊管理器實現(xiàn)。一切“正常”。我特別喜歡自動生成的文檔。對于這些工具,Python 提供的選項有點太簡單,需要小心對待,正如我之前提到的,Go 有一種奇怪的管理模塊方式,但除此之外,它的工具比 Python 的更好。

編輯器插件:我的. vimrc 文件大到令人尷尬,至少有三十多個插件。我有一些用于代碼檢查、自動補全以及格式化 Python 和 Go 的插件,但相比于其他兩種語言,Rust 插件更容易設(shè)置,更有用、更一致。 rust.vim 和 vim-lsp 插件(以及 Rust 語言服務(wù)器)是我獲得一個非常強大的配置所需要的全部。我還沒有測試其他編輯器,但是,借助 Rust 提供的編輯器無關(guān)的優(yōu)秀工具,我認為它們一樣有幫助。這個設(shè)置提供了我使用過的最好的“轉(zhuǎn)到定義”。它可以很好地適用于本地、標準庫和開箱即用的第三方代碼。

調(diào)試:我還沒有嘗試過 Rust 的調(diào)試器(因為其類型系統(tǒng)和 println! 已經(jīng)讓我走得很遠),但是你可以使用 rust-gdb 和 rust-lldb,以及 rustup 初始安裝時帶有的 gdb 和 lldb 調(diào)試器的封裝器。如果你之前在編寫 C 語言代碼時使用過那些調(diào)試器,那么其使用體驗將是意料之中的。正如前面提到的,編譯器的錯誤消息非常有幫助。

Rust 總結(jié)

你至少要讀過這本書的前幾章,否則我絕對不建議你嘗試編寫 Rust 代碼,即使你已經(jīng)熟悉 C 和內(nèi)存管理。對于 Go 和 Python,只要你有一些另一種現(xiàn)代命令式編程語言的經(jīng)驗,它們就不是很難入手,必要時可以參考文檔。Rust 是一門很大的語言。Python 也有很多特性,但是它們大部分是可選的。只要理解一些基本的數(shù)據(jù)結(jié)構(gòu)和一些內(nèi)置函數(shù),你就可以完成很多工作。對于 Rust,你需要真正理解類型系統(tǒng)的固有復雜性和借用檢查,否則你會搞得十分復雜。

就我寫 Rust 時的感覺而言,它非常有趣,就像 Python 一樣。它廣泛的特性使它很有表現(xiàn)力。雖然編譯器會經(jīng)常讓你停下,但它也非常有用,而且它對于如何解決你的借用問題 / 輸入問題的建議通常是有效的。正如我所提到的,這些工具是我遇到的所有語言中最好的,并且不像我使用的其他一些語言那樣給我?guī)砗芏嗦闊。我非常喜歡使用這種語言,并將在 Python 的性能還不夠好的地方繼續(xù)尋找使用 Rust 的機會。

代碼示例

我提取了每個 diffimg 中計算差異比的代碼塊。為了概括介紹 Python 的做法,這需要 Pillow 生成的差異圖像,對所有通道的所有像素值求和,并返回最大可能值(相同大小的純白圖像)除以總和的比值。

Python

diff_img = ImageChops.difference(im1, im2)
stat = ImageStat.Stat(diff_img)
sum_channel_values = sum(stat.mean)
max_all_channels = len(stat.mean) * 255
diff_ratio = sum_channel_values / max_all_channels

對于 Go 和 Rust,方法有點不同:我們不用創(chuàng)建一個差異圖像,我們只要遍歷兩幅輸入圖像,并對每個像素的差異求和。在 Go 中,我們用坐標索引每幅圖像……

Go

func GetRatio(im1, im2 image.Image, ignoreAlpha bool) float64 {
var sum uint64
width, height := getWidthAndHeight(im1)
for y := 0; y < height; y++ {
for x := 0; x < width; x++ {
sum += uint64(sumPixelDiff(im1, im2, x, y, ignoreAlpha))
}
}
var numChannels = 4
if ignoreAlpha {
numChannels = 3
}
totalPixVals := (height * width) * (maxChannelVal * numChannels)
return float64(sum) / float64(totalPixVals)
}

……但在 Rust 中,我們將圖像視為它們真的是在內(nèi)存中,是一系列可以壓縮到一起并消費的字節(jié)。

Rust

pub fn calculate_diff(
image1: DynamicImage,
image2: DynamicImage
) -> f64 {
let max_val = u64::pow(2, 8) - 1;
let mut diffsum: u64 = 0;
for (&p1, &p2) in image1
.raw_pixels()
.iter()
.zip(image2.raw_pixels().iter()) {
diffsum += u64::from(abs_diff(p1, p2));
}
let total_possible = max_val * image1.raw_pixels().len() as u64;
let ratio = diffsum as f64 / total_possible as f64;

ratio
}

對于這些例子,有一些事情需要注意:

Python 的代碼最少。顯然,這在很大程度上取決于使用的圖像庫,但這說明了使用 Python 的一般體驗。在許多情況下,那些庫為你做了很多工作,因為生態(tài)系統(tǒng)非常發(fā)達,任何東西都有成熟的解決方案。

在 Go 和 Rust 示例中有類型轉(zhuǎn)換。每個代碼塊中都使用了三個數(shù)值類型:用于像素通道值的 uint8/u8(Go 和 Rust 有類型推斷,所以你看不到任何明確提及的類型)、用于總和的 uint64/u64 和用于最終比值的 float64/f64。對于 Go 和 Rust,需要花時間統(tǒng)一類型,而 Python 將隱式地完成這一切。

Go 實現(xiàn)的風格是命令式的,但也是明確和可以理解的(使其稍顯欠缺的是我前面提到的 ignoreAlpha),甚至是對那些不習慣該語言的人也是如此。Python 示例相當清晰,一旦你理解了 ImageStat 在做什么。對于那些不熟悉這種語言的人來說,Rust 肯定更加難懂:

.raw_pixels() 獲取圖像,生成 8 位無符號整數(shù)向量;

.iter() 為該向量創(chuàng)建一個迭代器。默認情況下,向量是不可遍歷的;

.zip() 你可能了解,它接受兩個迭代器,然后生成一個迭代器,每個元素是一個元組:(來自第一個向量的元素,來自第二個向量的元素);

在 diffsum 聲明中,我們需要一個 mut,因為變量默認是不可變的;

如果你熟悉 C,你就會明白為什么 for (&p1, &p2) 中有 &:迭代器生成像素值的引用,但 abs_diff() 自己取得它們的值。Go 支持指針(和引用不太一樣),但它們不同于 Rust 中常用的引用。

函數(shù)中的最后一個語句用于在沒有行結(jié)束符 ; 的情況作為返回值。其他一些函數(shù)式語言也是這樣做的。

這段是為了讓你了解需要掌握多少特定于語言的知識才能有效地使用 Rust。

性能

現(xiàn)在來做一個科學的比較。我首先生成三張不同尺寸的隨機圖像:1x1、2000x2000、10000x10000。然后我測量每個(語言、圖像大小)組合的性能,每個 diffimg 計算 10 次,然后取平均值,使用 time 命令的 real 值給出的值。diffimg-rs 使用–release 構(gòu)建,diffimg-go 使用 go build,而 Python diffimg 通過 python3 - m diffimg 調(diào)用。以下是在 2015 年的 Macbook Pro 上獲得的結(jié)果:

我損失了很多精度,因為 time 只精確到 10ms(因為計算平均值的緣故,這里多顯示了一個數(shù)字)。該任務(wù)只需要一個非常特定類型的計算,所以不同的或更復雜的任務(wù)得出的數(shù)值可能差別很大。話雖如此,我們還是可以從這些數(shù)據(jù)中了解到一些東西。

對于 1x1 的圖像,幾乎所有的時間都花費在設(shè)置中,沒有比例計算。Rust 獲勝,盡管它使用了兩個第三方庫( clap 和 image ),Go 只使用了標準庫。我并不驚訝 Python 的啟動那么緩慢,因為導入大庫 Pillow 是它的一個步驟,time python -c ’ '其實只用了 0.030 秒。

對于 2000x2000 的圖像,Go 和 Python 與 Rust 的差距就縮小了,這大概是因為與計算相比,用于設(shè)置的時間更少。然而,對于 10000 年 x10000 的圖像,Rust 相比較之下性能更好,我想這是由于其編譯器優(yōu)化所生成的機器代碼最小(循環(huán) 1 億次),設(shè)置時間相對就比較少了。從不需要暫停進行垃圾收集也是一個因素。

Python 實現(xiàn)肯定還有很大的改進余地,因為像 Pillow 那么高效,我們?nèi)匀皇窃趦?nèi)存中創(chuàng)建一張差異圖像(遍歷輸入圖像),然后累加每個像素的通道值。更直接的方法,比如 Go 和 Rust 實現(xiàn),可能會稍微快一些。然而,純 Python 實現(xiàn)會非常慢,因為 Pillow 主要是用 C 完成其工作。因為另外兩個是純粹用一種語言實現(xiàn)的,這不是一個真正公平的比較,雖然在某些方面是,因為得益于 C 擴展(Python 和 C 的關(guān)系一般都非常緊密 ),Python 有一大堆高性能庫可以使用。

我還應(yīng)該提下二進制文件的大。篟ust 的 2.1MB,使用–release 構(gòu)建,Go 的大小差不多,為 2.5 MB。Python 不創(chuàng)建二進制文件,但是.pyc 文件有一定的可比性,和 diffimg 的.pyc 文件總共約 3 KB。它的源代碼也只有 3KB,但是包括 Pillow 依賴的話,它將達 24MB。再說一次,這不是一個公平的比較,因為我使用了一個第三方圖像庫,但應(yīng)該提一下。

結(jié)論

顯然,這三種截然不同的語言實現(xiàn)滿足不同的細分市場需求。我經(jīng)常聽到 Go 和 Rust 被一起提及,但我認為,Go 和 Python 是兩種類似 / 存在競爭關(guān)系的語言。它們都很適合編寫服務(wù)器端應(yīng)用程序邏輯(我在工作中大部分時間都在做這項工作)。僅比較原生代碼的性能,Go 完勝 Python,但許多有速度要求的 Python 庫是對速度更快的 C 實現(xiàn)的封裝——實際情況比這種天真的比較更復雜。編寫一個用于 Python 的 C 擴展不能完全算是 Python 了(你需要了解 C),但這個選項是對你開放的。

對于你的后端服務(wù)器需求,Python 已被證明它對于大多數(shù)應(yīng)用程序都“足夠快”,但是如果你需要更好的性能,Go 可以,Rust 更是如此,但是你要付出更多的開發(fā)時間。Go 在這方面并沒有超出 Python 很多,雖然開發(fā)肯定是慢一些,這主要是由于其較小的特性集。Rust 的特性非常齊全,但管理內(nèi)存總是比由語言自己管理會花費更多的時間,這好過處理 Go 的極簡性。

還應(yīng)該提一下,世界上有很多很多 Python 開發(fā)人員,有些有幾十年的經(jīng)驗。如果你選擇 Python,那么找到更多有語言經(jīng)驗的人加入到你的后端團隊中可能并不難。然而,Go 開發(fā)人員并不是特別少,而且很容易發(fā)展,因為這門語言很容易學習。由于 Rust 這種語言需要更長的時間內(nèi)化,所以開發(fā)人員更少,也更難發(fā)展。

至于系統(tǒng)類型:靜態(tài)類型系統(tǒng)更容易編寫更多正確的代碼,但它不是萬能的。無論使用何種語言,你仍然需要編寫綜合測試。它需要更多的訓練,但是我發(fā)現(xiàn),我使用 Python 編寫的代碼并不一定比 Go 更容易出錯,只要我能夠編寫一個好的測試套件。盡管如此,相比于 Go,我更喜歡 Rust 的類型系統(tǒng):它支持泛型、模式匹配、錯誤處理,它通常為你做得更多。

最后,這種比較有點愚蠢,因為盡管這些語言的用例重疊,但它們占領(lǐng)著不同的細分市場。Python 開發(fā)速度快、性能低,而 Rust 恰恰相反,Go 則介于兩者之間。我喜歡 Python 和 Rust 超過 Go(這可能令人奇怪),不過我會繼續(xù)在工作中愉快地使用 Go(以及 Python),因為它真的是一種構(gòu)建穩(wěn)定、可維護的應(yīng)用程序的偉大語言,它有許多來自不同背景的貢獻者。它的僵硬和極簡主義使它使用起來不那么令人愉快(對我來說),但這也正是它的力量所在。如果我要為一個新的 Web 應(yīng)用程序選擇后端語言的話,那將是 Go。

我對這三種語言所涵蓋的編程任務(wù)范圍相當滿意——實際上,沒有哪個項目不能把它們中的一種視為很好的選擇。

查看英文原文:One Program Written in Python, Go, and Rust

標簽: Python

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

上一篇:超越云計算:對數(shù)據(jù)庫管理系統(tǒng)未來的思考

下一篇:Python小技巧:3個處理文件路徑的簡單方法