Rust VS Python:為什么越來(lái)越流行,取代榜一Python?
2021 年,Python 又獲得了 TIOBE 年度編程語(yǔ)言,排名已經(jīng)是第一。而 Rust 依然在 20 名以外。但依然有人認(rèn)為,Rust 甚至可能取代 Python。不過(guò)這不重要,認(rèn)清兩者的優(yōu)缺點(diǎn),進(jìn)而合適的地方使用合適的語(yǔ)言,這才最重要。
在這個(gè)指南中,我們將比較 Rust 和 Python 這兩門(mén)語(yǔ)言,同時(shí)將討論它們各自的應(yīng)用場(chǎng)景,回顧使用 Rust vs. Python 的優(yōu)缺點(diǎn),并解釋 Rust 為什么越來(lái)越受歡迎(甚至可能取代 Python)。
01 Rust 是什么?
Rust [1] 是一門(mén)系統(tǒng)編程語(yǔ)言,專(zhuān)注于安全,尤其是并發(fā)安全,支持函數(shù)式和命令式以及泛型等編程范式的多范式語(yǔ)言。Rust 在語(yǔ)法上和 C++ 類(lèi)似,但是設(shè)計(jì)者想要在保證性能的同時(shí)提供更好的內(nèi)存安全。Rust 最初是由 Mozilla 研究院的 Graydon Hoare 設(shè)計(jì)創(chuàng)造,然后在 Dave Herman, Brendan Eich 以及很多其他人的貢獻(xiàn)下逐步完善的。Rust 的設(shè)計(jì)者們通過(guò)在研發(fā) Servo 網(wǎng)站瀏覽器布局引擎過(guò)程中積累的經(jīng)驗(yàn)優(yōu)化了 Rust 語(yǔ)言和 Rust 編譯器。
Rust 擁有 優(yōu)秀的文檔 [2] 、友好的編譯器和有用的錯(cuò)誤消息,以及頂級(jí)工具,包括集成包管理器、構(gòu)建工具、支持自動(dòng)完成和類(lèi)型檢查的智能多編輯器、自動(dòng)格式化程序等等。
Rust 發(fā)布于 2010 年。雖然和 Python 相比,Rust 是一門(mén)年輕的語(yǔ)言,但是它的社區(qū)正在穩(wěn)步增長(zhǎng)。事實(shí)上,Rust 已經(jīng)連續(xù)五年(2016,2017,2018,2019,2020)在 Stack Overflow 開(kāi)發(fā)者調(diào)查的“最受喜愛(ài)編程語(yǔ)言”評(píng)選項(xiàng)目中摘取桂冠。
乍一看,Rust 的靜態(tài)化和強(qiáng)類(lèi)型化可能看起來(lái)有點(diǎn)極端。但從長(zhǎng)遠(yuǎn)來(lái)看,這有助于防止意外的代碼行為。
02 Python 是什么?
Python [3] 是一門(mén)旨在幫助開(kāi)發(fā)人員更有效地工作和更有效地集成系統(tǒng)的編程語(yǔ)言。Python 提供了高效的高級(jí)數(shù)據(jù)結(jié)構(gòu),還能簡(jiǎn)單有效地面向?qū)ο缶幊?。Python 語(yǔ)法和動(dòng)態(tài)類(lèi)型,以及解釋型語(yǔ)言的本質(zhì),使它成為多數(shù)平臺(tái)上寫(xiě)腳本和快速開(kāi)發(fā)應(yīng)用的編程語(yǔ)言,隨著版本的不斷更新和語(yǔ)言新功能的添加,逐漸被用于獨(dú)立的、大型項(xiàng)目的開(kāi)發(fā)。如果速度是最重要的,可以使用較低級(jí)別的 API 調(diào)用,如 CPython [4] 。
1991 年 Guido van Rossum 推出了 Python,以其代碼的可讀性、無(wú)分號(hào)和花括號(hào)而著稱(chēng)。
除了可擴(kuò)展性之外,Python 還是一門(mén)解釋型語(yǔ)言,這使得它比大多數(shù)編譯型語(yǔ)言要慢。正如您可能期望的那樣,Python 擁有一個(gè)龐大的庫(kù)生態(tài)系統(tǒng)和一個(gè)龐大的專(zhuān)業(yè)社區(qū)。
03 什么時(shí)候使用 Rust
Rust 被應(yīng)用于系統(tǒng)開(kāi)發(fā)、操作系統(tǒng)、企業(yè)系統(tǒng)、微控制器應(yīng)用、嵌入式系統(tǒng)、文件系統(tǒng)、瀏覽器組件、虛擬現(xiàn)實(shí)的仿真引擎等。
當(dāng)性能很重要的時(shí)候,Rust 是一種常用的語(yǔ)言,因?yàn)樗芎芎玫靥幚泶罅繑?shù)據(jù)。它可以處理 CPU 密集型的操作,如執(zhí)行算法,這就是為什么 Rust 比 Python 更適合系統(tǒng)開(kāi)發(fā)的原因。
Rust 保證了內(nèi)存的安全性,讓你可以控制線程行為和線程之間的資源分配方式。這使你能夠構(gòu)建復(fù)雜的系統(tǒng),也使得 Rust 比 Python 更有優(yōu)勢(shì)。
總而言之,你應(yīng)在以下情況下使用 Rust:
- 你的項(xiàng)目需要高性能
- 你正在構(gòu)建復(fù)雜的系統(tǒng)
- 你重視內(nèi)存安全而不是簡(jiǎn)單性
04 什么時(shí)候使用 Python
Python 可以用于許多應(yīng)用領(lǐng)域,從 Web 開(kāi)發(fā),到數(shù)據(jù)科學(xué)和分析,到 AI 和機(jī)器學(xué)習(xí),再到軟件開(kāi)發(fā)。
Python 被廣泛用于機(jī)器學(xué)習(xí),數(shù)據(jù)科學(xué)和 AI,因?yàn)樗?/p>
- 簡(jiǎn)單且容易
- 靈活
- 包含大量面向數(shù)據(jù)的軟件包和庫(kù)
- 有出色的工具和庫(kù)生態(tài)系統(tǒng)支持
在以下情況下,你應(yīng)該使用 Python:
- 你需要一種靈活的語(yǔ)言來(lái)支持 Web 開(kāi)發(fā),數(shù)據(jù)科學(xué)和分析以及機(jī)器學(xué)習(xí)和 AI
- 你重視可讀性和簡(jiǎn)單性
- 你需要一種對(duì)初學(xué)者友好的語(yǔ)言
- 與性能相比,你更喜歡語(yǔ)法簡(jiǎn)單和開(kāi)發(fā)速度
05 為什么 Rust 可以取代 Python
考慮到 Rust 的迅速普及、受歡迎程度和廣泛的使用案例,它幾乎不可避免地會(huì)在不久的將來(lái)超越 Python,以下是一些原因。
性能
Rust 超越 Python 的一個(gè)主要原因是性能。因?yàn)?Rust 是直接編譯成機(jī)器代碼的,所以在你的代碼和計(jì)算機(jī)之間沒(méi)有虛擬機(jī)或解釋器。
與 Python 相比,另一個(gè)關(guān)鍵優(yōu)勢(shì)是 Rust 的線程和內(nèi)存管理。雖然 Rust 不像 Python 那樣有垃圾回收機(jī)制,但 Rust 中的編譯器會(huì)強(qiáng)制檢查無(wú)效的內(nèi)存引用泄漏和其他危險(xiǎn)或不規(guī)則行為。
編譯語(yǔ)言通常比解釋語(yǔ)言要快。但是,使 Rust 處于不同水平的是,它幾乎與 C 和 C ++一樣快,而且沒(méi)有額外開(kāi)銷(xiāo)。
讓我們看一個(gè)用 Python 編寫(xiě)的 O(log n) 程序的示例,并使用迭代方法計(jì)算完成任務(wù)所需的時(shí)間:
- import random
- import datetime
- def binary_searcher(search_key, arr):
- low = 0
- high = len(arr)-1
- while low <= high:
- mid = int(low + (high-low)//2)
- if search_key == arr[mid]:
- return True
- if search_key < arr[mid]:
- high = mid-1
- elif search_key > arr[mid]:
- low = mid+1
- return False
輸出:
- > python -m binny.py
- It took 8.6μs to search
現(xiàn)在,讓我們來(lái)看一下使用迭代方法用 Rust 編寫(xiě)的定時(shí) O(log n) 程序:
- >use rand::thread_rng;
- use std::time::Instant;
- use floating_duration::TimeFormat;
- fn binary_searcher(search_key: i32, vec: &mut Vec<i32>) -> bool {
- let mut low: usize = 0;
- let mut high: usize = vec.len()-1;
- let mut _mid: usize = 0;
- while low <= high {
- _mid = low + (high-low)/2;
- if search_key == vec[_mid] {
- return true;
- }
- if search_key < vec[_mid] {
- high = _mid - 1;
- } else if search_key > vec[_mid] {
- low = _mid + 1;
- }
- }
- return false;
- }
- fn main() {
- let mut _rng = thread_rng();
- let mut int_vec = Vec::new();
- let max_num = 1000000;
- for num in 1..max_num {
- int_vec.push(num as i32);
- }
- let start = Instant::now();
- let _result = binary_searcher(384723, &mut int_vec);
- println!("It took: {} to search", TimeFormat(start.elapsed()));
- }
輸出:
- > cargo run
- Finished dev [unoptimized + debuginfo] target(s) in 0.04s
- Running target\debug\algo_rusty.exe
- It took: 4.6μs to search
在沒(méi)有使用任何優(yōu)化技術(shù)的情況下,Rust 和 Python 在同一臺(tái)機(jī)器上執(zhí)行類(lèi)似的操作分別需要 4.6 微秒和 8.6 微秒。這意味著 Python 花費(fèi)的時(shí)間幾乎是 Rust 的兩倍。
內(nèi)存管理
Python 和大多數(shù)現(xiàn)代編程語(yǔ)言一樣,被設(shè)計(jì)成內(nèi)存安全的。然而,即使沒(méi)有垃圾回收。Rust 在內(nèi)存安全方面卻讓 Python 望塵莫及。
Rust 采用了一種獨(dú)特的方式來(lái)確保內(nèi)存安全,其中涉及所有權(quán)系統(tǒng)和借用檢查器(borrow checker)。Rust 的借用檢查器確保引用和指針不會(huì)超過(guò)它們所指向的數(shù)據(jù)。
錯(cuò)誤檢查與診斷
Python 和其他語(yǔ)言一樣,提供了錯(cuò)誤檢查和日志機(jī)制。但是在讓開(kāi)發(fā)者知道哪里出了什么問(wèn)題的時(shí)候,Rust 和 Python 之間有一些差異。
舉一個(gè) Python 變量錯(cuò)誤的典型例子:
- apple = 15
- print('The available apples are:', aple)
Python 輸出:
- Traceback (most recent call last):
- File "binny.py", line 2, in <module>
- print('The available apples are:', aple)
- NameError: name 'aple' is not defined
Rust 中的類(lèi)似示例:
- fn main() {
- let apple = 15;
- println!("The available apples are:", aple);
- }
Rust 輸出:
- println!("The available apples are:", aple);
- ^^^^ help: a local variable with a similar name exists: `apple`
在這里,Rust 推薦了可能的變量,這些變量可能是你想輸入的。Python 只會(huì)拋出錯(cuò)誤,而不會(huì)給出如何修復(fù)的建議。
再舉個(gè)例子:
- fn main() {
- let grass = 13;
- grass += 1;
- }
此代碼引發(fā)錯(cuò)誤,因?yàn)槟J(rèn)情況下 Rust 中的變量是不可變的。除非它具有關(guān)鍵字 mut ,否則無(wú)法更改。
錯(cuò)誤:
- let grass = 13;
- | -----
- | |
- | first assignment to `grass`
- | help: make this binding mutable: `mut grass`
修正錯(cuò)誤:
- fn main() {
- let mut _grass: i32 = 13;
- _grass += 1;
- }
如你所見(jiàn),現(xiàn)在它不會(huì)引發(fā)任何錯(cuò)誤。除此之外,Rust 不允許不同的數(shù)據(jù)類(lèi)型相互操作,除非將它們轉(zhuǎn)換為相同的類(lèi)型。
因此,維護(hù) Rust 代碼庫(kù)通常很容易。除非指定,否則 Rust 不允許更改。Python 是允許這種性質(zhì)的更改的。
與大多數(shù)編譯語(yǔ)言相比,Rust 因其速度快、內(nèi)存安全有保證、超強(qiáng)的可靠性、一致性和用戶友好性而備受青睞。在編程中,我們已經(jīng)到了速度開(kāi)始變得毫不費(fèi)力的地步。
隨著技術(shù)的發(fā)展,它變得越來(lái)越快,試圖在更短的時(shí)間內(nèi)做更多的事情,而不需要那么多的權(quán)衡。Rust 幫助實(shí)現(xiàn)了這一點(diǎn),同時(shí)又不妨礙開(kāi)發(fā)者的工作。當(dāng)技術(shù)試圖推動(dòng)可以實(shí)現(xiàn)的邊界時(shí),它也會(huì)考慮系統(tǒng)的安全性和可靠性,這是 Rust 背后的主要思想。
并行運(yùn)算
除了速度外,Python 在并行計(jì)算方面也有局限性。
Python 使用全局解釋器鎖(GIL),它鼓勵(lì)只有一個(gè)線程同時(shí)執(zhí)行,以提高單線程的性能。這是一大局限,因?yàn)樗馕吨悴荒苁褂枚鄠€(gè) CPU 核進(jìn)行密集計(jì)算。
社區(qū)
如前所述,Stack Overflow 的“ 2020 開(kāi)發(fā)人員調(diào)查”中有 86%的受訪者將 Rust 稱(chēng)為 2020 年最喜歡的編程語(yǔ)言。
同樣,“ 2020 HackerRank 開(kāi)發(fā)人員技能報(bào)告”的受訪者將 Rust 列為他們計(jì)劃下一步學(xué)習(xí)的十大編程語(yǔ)言:
相比之下,2019 年的調(diào)查將 Rust 排在列表的底部,這表明 Rust 開(kāi)發(fā)人員社區(qū)正在迅速增長(zhǎng)。
這些數(shù)據(jù)表明,Rust 正在成為主流開(kāi)發(fā)者社區(qū)的一部分。許多大公司都在使用 Rust,一些開(kāi)發(fā)者甚至用它來(lái)構(gòu)建其他編程語(yǔ)言使用的庫(kù)。著名的 Rust 用戶包括 Mozilla、Dropbox、Atlassian、npm 和 Cloudflare 等等。
Amazon Web Service 還對(duì) Lambda,EC2 和 S3 中的性能敏感組件采用了 Rust。在 2019 年,AWS 宣布贊助 Rust 項(xiàng)目,此后為 Rust 提供了 AWS 開(kāi)發(fā)工具包。
公司正越來(lái)越多地用更高效的編程語(yǔ)言(如 Rust)取代速度較慢的編程語(yǔ)言。沒(méi)有其他語(yǔ)言能像 Rust 一樣在簡(jiǎn)單和速度之間做出平衡。
06 總結(jié)
Rust 已經(jīng)發(fā)展成為一門(mén)易于使用的編程語(yǔ)言,因此它的使用率有所提高。盡管 Python 在機(jī)器學(xué)習(xí)/數(shù)據(jù)科學(xué)社區(qū)中占有堅(jiān)實(shí)的地位,但 Rust 在未來(lái)很可能被用作 Python 庫(kù)更有效的后端。
Rust 具有取代 Python 的巨大潛力。目前的趨勢(shì)是,在應(yīng)用程序、性能和速度方面,Rust 不僅僅是一種編程語(yǔ)言,它還是一種思維方式。