日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當前位置:首頁 > 科技  > 軟件

Python vs. Rust:打破三大障礙

來源: 責編: 時間:2024-05-21 17:30:29 216觀看
導讀在我周圍的每個人都知道我是Python 的忠實粉絲。大約15年前,當我對 Mathworks Matlab 感到厭倦時,我開始使用Python。雖然Matlab的理念看起來不錯,但在掌握了Python之后,我再也沒有回頭。我甚至成為了我所在大學的Python

在我周圍的每個人都知道我是Python 的忠實粉絲。大約15年前,當我對 Mathworks Matlab 感到厭倦時,我開始使用Python。雖然Matlab的理念看起來不錯,但在掌握了Python之后,我再也沒有回頭。我甚至成為了我所在大學的Python傳道者,"傳播這個詞"。QPT28資訊網——每日最新資訊28at.com

QPT28資訊網——每日最新資訊28at.com

會編碼并不等于成為軟件開發者。當我了解到強類型、SOLID原則和通用編程架構等主題時,我也瞥見了其他編程語言以及它們如何解決問題。特別是Rust引起了我的興趣,因為我經常看到基于Rust的Python包(例如Polars)。QPT28資訊網——每日最新資訊28at.com

QPT28資訊網——每日最新資訊28at.com

為了對Rust有一個合適的介紹,我參加了官方的Rustlings課程,這是一個包含96個小型編碼問題的本地Git存儲庫。盡管這是相當可行的,但Rust與Python非常不同。Rust編譯器是一個非常嚴格的家伙,不接受"也許"這個答案。以下是我認為Rust和Python之間的三個主要區別。QPT28資訊網——每日最新資訊28at.com

QPT28資訊網——每日最新資訊28at.com

免責聲明:雖然我對Python相當熟練,但我對其他語言了解有點生疏。我仍在學習Rust,可能對某些部分有誤解。QPT28資訊網——每日最新資訊28at.com

QPT28資訊網——每日最新資訊28at.com

QPT28資訊網——每日最新資訊28at.com

QPT28資訊網——每日最新資訊28at.com

1. 所有權、借用和生命周期

QPT28資訊網——每日最新資訊28at.com

所有權和借用可能是Rust編程語言最基本的方面。它旨在確保內存安全,而無需所謂的垃圾收集器。這是Rust的一個獨特概念,我尚未在其他語言中看到過。讓我們以一個例子開始,我們將值42分配給變量answer_of_life。Rust現在將在內存中分配一些空間(這有點復雜,但現在我們簡化一下),并將"所有權"附加到這個變量上。重要的是要知道一次只能有一個所有者。一些操作會"轉移所有權",使先前的變量引用無效。這通過防止諸如雙重釋放內存、數據競爭和懸空引用等問題來確保內存安全。QPT28資訊網——每日最新資訊28at.com

fn main() {  let s1 = String::from("Hello, Rust!");    // Ownership of the String is transferred from s1 to s2  let s2 = s1;    // This results in a compilation  println!("s1: {}", s1);} // s2 goes out of scope and memory is freed

一個在其他語言中也使用的術語是作用域。這可以被看作是代碼中的一個"生存區"。每當代碼離開一個作用域時,所有具有所有權的變量都將被釋放。這在Python中是根本不同的事情。Python使用垃圾收集器,在沒有對其的引用時釋放變量。在Source 1的例子中,將所有權從變量s1轉移到s2,此后變量s1將無法使用。QPT28資訊網——每日最新資訊28at.com

QPT28資訊網——每日最新資訊28at.com

對于Python用戶來說,所有權可能會令人困惑,因為在開始階段確實是一場真正的斗爭。在Source 1的例子中有點過于簡單了。Rust強制你考慮一個變量是在哪里創建的以及它應該如何被轉移。例如,當你將參數傳遞給函數時,所有權可以如Source 2中所示被轉移。QPT28資訊網——每日最新資訊28at.com

fn take_ownership(some_string: String) {  // The ownership of the String is transferred to some_string  println!("Got ownership: {}", some_string);}  // some_string goes out of scope and the memory is freedfn main() {  let my_string = String::from("Hello, ownership!");  // Ownership is transferred to the function and my_string is  // no longer valid  take_ownership(my_string);  // This results in a compilation error as my_string is no  // longer the owner of the String.  println!("my_string: {}", my_string);} // my_string is no longer valid here, as it was moved to take_ownership

僅僅轉移所有權可能很麻煩,對于某些用例甚至可能行不通,因此Rust提出了所謂的借用系統。與轉移所有權不同,變量同意借用該變量,而原始變量仍保持所有權。默認情況下,借用變量是不可變的,即只讀的,但通過添加mut關鍵字,借用甚至可以是可變的。在Source 3中,我展示了兩個不可變的借用和一個可變的借用的例子。當函數超出范圍時,所有變量都將被刪除。QPT28資訊網——每日最新資訊28at.com

fn main() {  // s is the owner of the mutable String  let mut s = String::from("Hello, Rust!");  let r1 = &s;  // Immutable borrow  let r2 = &s;  // Another immutable borrow  println!("r1: {}, r2: {}", r1, r2);  let r3 = &mut s;  // Mutable borrow  r3.push_str(", and Pythonista!"); // Modifying the borrowed value  println!("r3: {}", r3);} // r1, r2, r3, and s go out of scope and memory is automagically freed

生命周期是Rust中與借用和所有權相關的一個概念,它幫助編譯器強制規定引用可以有效存在多長時間的規則。你可能會遇到這樣一種情況,你創建了一個結構或一個函數,它是使用兩個借用構建的。這意味著現在函數或結構的結果可能取決于先前的輸入。為了更明確地表示這一點,我們可以通過注釋生命周期來表達關系。在Source 4中查看一個例子。QPT28資訊網——每日最新資訊28at.com

struct Quote<'a> {  part: &'a str,}  // We annotated this Struct such that its lifetime is linked to partfn main() {  let novel = String::from("Do or do not. There is not try.");  // We split novel on the period but split returns borrows.  // This means that if novel goes out of scope, so does first_sentence.  let first_sentence = novel.split('.')          .next().expect("No period detected!");     // We have annotated the lifetime to be dependent of part.  // If first_sentence goes out of scope, so does quote.  let quote = Quote {    part: first_sentence,  };}  // All will be deallocated

QPT28資訊網——每日最新資訊28at.com

2. Rust 不接受 None 為答案

QPT28資訊網——每日最新資訊28at.com

在Python中非常常見的一點在Rust中是不可能的:擁有一個值被設置為 None。這是一個刻意的設計選擇,符合Rust的安全性、可預測性和零成本抽象的目標。安全性方面與Rust的所有權、借用和生命周期方面相似:防止引用指向未分配的內存的可能性。通過不給予返回 None 的可能性,將導致更可預測性,因為它強迫開發者明確處理數字可能不存在的情況。由于內存安全和可預測的行為,Rust可以在不犧牲性能的情況下實現其所有高級語言功能。QPT28資訊網——每日最新資訊28at.com

QPT28資訊網——每日最新資訊28at.com

僅僅拒絕 None 會使 Rust 變得糟糕,因此,創建者提出了一個不錯的替代方案:枚舉 Option 和 Result。通過這些枚舉,我們可以明確表示值的存在或不存在。它還使錯誤處理變得非常優雅。讓我們考慮 Source 5 中使用 Option 的一個示例。QPT28資訊網——每日最新資訊28at.com

fn divide(x: f64, y: f64) -> Option<f64> {  if y == 0.0 {    None  } else {    Some(x / y)  }}  fn main() {  let result = divide(10.0, 2.0);    match result {    Some(value) => println!("Result: {}", value),    None => println!("Cannot divide by zero!"),  }}

等一下!你不是說沒有 None 嗎?這也是我第一次被欺騙的地方,但在這里,None 是一個不帶參數的特殊枚舉結構。同樣,Some 也是一個特殊的結構,但它可以帶一個參數。我們的 divide() 函數返回這些可能的枚舉值之一,我們稍后可以檢查它是什么并采取相應的操作。QPT28資訊網——每日最新資訊28at.com

QPT28資訊網——每日最新資訊28at.com

沒有 None 并強制返回值使得 Rust 變得非常可預測。QPT28資訊網——每日最新資訊28at.com

QPT28資訊網——每日最新資訊28at.com

主函數使用 match 結構進行結果處理,這非常方便。這在某種程度上類似于其他語言中的 switch/case 構造,除了 Python(見圖2中Guido的回應)。match 檢查是枚舉 Some 還是枚舉 None,并執行相應的操作。QPT28資訊網——每日最新資訊28at.com

QPT28資訊網——每日最新資訊28at.com

Option 枚舉是用于可以返回值或不返回值的函數的特殊結構。對于可以返回值或錯誤的函數,Rust 還有一個更明確的枚舉,稱為 Result。思想完全相同,主要區別在于 Option 有一個默認的“錯誤”值 None,而 Result 需要一個顯式的“錯誤”類型。在 Source 6 中,divide 函數使用 Result 重寫。QPT28資訊網——每日最新資訊28at.com

fn divide(x: f64, y: f64) -> Result<f64, &'static str> {  if y == 0.0 {    Err("Cannot divide by zero!")  } else {    Ok(x / y)  }}  fn main() {  let result = divide(10.0, 0.0);    match result {    Ok(value) => println!("Result: {}", value),    Err(err) => println!("Error: {}", err),  }}

Rust的開發者們看到match結構有時可能有點繁瑣,因此添加了if let和while let運算符。這些運算符類似于match,但通過一些美味的糖分提供了一些不錯的語法糖。甚至還有一個非常酷的?運算符(此處未顯示),為美味的糖分添加了一顆櫻桃!QPT28資訊網——每日最新資訊28at.com

let mut values = vec![Some(1), Some(2), None, Some(3)];while let Some(value) = values.pop() {  if let Some(inner_value) = value {    println!("Popped: {}", inner_value);  } else {    println!("Found None");  }}

使用Python時,我學會了使用Optional關鍵字為結果類型化,可以是值,也可以是None。但我不得不承認Rust非常巧妙地解決了這一部分。我可以想象Python社區也會朝著這種風格發展,類似于強(更強)類型化的趨勢。QPT28資訊網——每日最新資訊28at.com

QPT28資訊網——每日最新資訊28at.com

3. 類在哪里?

QPT28資訊網——每日最新資訊28at.com

Python和Rust都可以用于兩種編程范式:函數式編程(FP)和面向對象編程(OOP)。但是Rust在實現這些所謂的對象的方式上有所不同。在Python中,我們有一個典型的類對象,我們可以將變量和方法與之關聯。與許多其他語言(如Java)一樣,我們現在可以將這個方法用作基礎,并通過創建繼承方法和變量的新對象來擴展功能。QPT28資訊網——每日最新資訊28at.com

QPT28資訊網——每日最新資訊28at.com

在Rust中,沒有class關鍵字,對象與Python基本不同。Rust使用Trait系統進行代碼重用和多態性,這可以提供與多重繼承相同的好處,但不會出現與多重繼承相關的問題。多重繼承通常用于將多個類的各種功能組合或共享,但它可能使代碼變得復雜和模糊。一個著名的問題是所謂的菱形問題,見Source 8。QPT28資訊網——每日最新資訊28at.com

class A:    def method(self):        print("Method in class A")class B(A):    def method(self):        print("Method in class B")class C(A):    def method(self):        print("Method in class C")        class D(B, C):    passobj = D()obj.method()  # Ambiguity arises here

盡管我認為我們可以輕松地解決這個問題,但如果我要創建一種新語言,我也會嘗試以不同的方式解決這個問題。對于多重繼承,目標主要是與其他對象共享類似的功能。在Rust中,使用Trait系統更加優雅地實現了這一點。這種方法不僅在Rust中使用,在Scala、Kotlin和Haskell等語言中也有類似的系統。QPT28資訊網——每日最新資訊28at.com

QPT28資訊網——每日最新資訊28at.com

在Rust中,類是由Enums和Structs創建的。就它們自身而言,它們只是數據結構,但我們可以向這些類添加功能。我們可以直接這樣做,然而,通過使用traits,這些功能可以與多個“類”共享。使用traits的一個重要好處是我們可以事先檢查某個trait是否已實現。請看以下示例:QPT28資訊網——每日最新資訊28at.com

// Define a trait for characters that can speaktrait Speaker {    fn speak(&self);}// Implement the Speaker trait for a Jedistruct Jedi {    name: String,}impl Speaker for Jedi {    fn speak(&self) {        println!("{} says: May the Force be with you.", self.name);    }}// Implement the Speaker trait for a Droidstruct Droid {    model: String,}impl Speaker for Droid {    fn speak(&self) {        println!("{} says: Beep boop beep.", self.model);    }}// Function that takes any type implementing the Speaker traitfn introduce(character: &dyn Speaker) {    character.speak();}fn main() {    let obi_wan = Jedi {        name: String::from("Obi-Wan Kenobi"),    };    let r2d2 = Droid {        model: String::from("R2-D2"),    };    // Call the introduce function with instances of Jedi and Droid    introduce(&obi_wan);    introduce(&r2d2);}

在這個例子中,我們有一個Speaker trait,代表可以說話的角色。我們為兩種類型實現了這個trait:Jedi和Droid。每種類型都提供了自己的speak方法的實現。introduce函數接受任何實現Speaker trait的類型,并調用speak方法。在主函數中,我們創建了Jedi(奧比-萬·克諾比)和Droid(R2-D2)的實例,并將它們傳遞給introduce函數,展示了多態性。QPT28資訊網——每日最新資訊28at.com

QPT28資訊網——每日最新資訊28at.com

對于我這個Pythonista  來說,Rust的trait系統曾經非常令人困惑。花了一些時間我才欣賞到其語法的優雅之處。QPT28資訊網——每日最新資訊28at.com

QPT28資訊網——每日最新資訊28at.com

總結

QPT28資訊網——每日最新資訊28at.com

Rust是一門非常酷的語言,但絕對不是一門容易學習的語言。Rustlings課程向我展示了一些基礎知識,但我遠遠不熟練到能夠承擔大型項目的程度。但我真的很喜歡Rust是如何迫使你編寫更好、更安全的代碼的。QPT28資訊網——每日最新資訊28at.com

QPT28資訊網——每日最新資訊28at.com

Python仍然是我的日常首選。在工作中,我們的文檔流水線完全由Python構建,而且在機器學習領域,我并沒有看到一切都轉向另一種語言。Python太容易學習了,即使你是一個糟糕的開發者,也能完成工作。QPT28資訊網——每日最新資訊28at.com

QPT28資訊網——每日最新資訊28at.com

然而,有一些小的動向朝著Rust。當然,一些包如Polars和Pydantic是使用Rust構建的,而HuggingFace也發布了他們自己用Rust構建的第一個版本的名為Candle的機器學習框架。因此,我認為學習一點Rust并不是一個壞主意!QPT28資訊網——每日最新資訊28at.com

本文鏈接:http://m.www897cc.com/showinfo-26-89710-0.htmlPython vs. Rust:打破三大障礙

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: .NET 6:生成單一可執行文件的應用

下一篇: Python 多線程編程的十個關鍵概念

標簽:
  • 熱門焦點
Top 日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不
久久精品官网| 亚洲欧美另类中文字幕| 亚洲高清在线观看| 亚洲精品在线免费| 一区二区三区精品| 欧美一级大片在线免费观看| 久久综合久久综合久久综合| 欧美日韩成人网| 国产酒店精品激情| 亚洲第一网站| 亚洲主播在线播放| 久久人人爽人人| 欧美日韩午夜视频在线观看| 国产日韩av一区二区| 91久久国产综合久久蜜月精品 | 亚洲激情网站| 亚洲专区一区二区三区| 久久午夜精品一区二区| 欧美日韩在线不卡一区| 国内精品美女在线观看| 一本色道婷婷久久欧美| 久久九九国产精品| 欧美日韩在线观看视频| 国产一区二区精品久久| 一本一道久久综合狠狠老精东影业| 久久精品国产v日韩v亚洲 | 久久精品一区二区| 欧美日韩免费观看一区三区| 一区免费观看| 亚洲综合成人在线| 欧美国产乱视频| 国内不卡一区二区三区| 亚洲一区二三| 欧美二区乱c少妇| 国产手机视频精品| 亚洲网站在线观看| 欧美成人免费播放| 国产原创一区二区| 亚洲免费在线观看| 欧美日韩高清在线播放| 亚洲大片av| 久久久精品一区| 国产精品一区二区三区乱码 | 亚洲尤物在线视频观看| 欧美激情一区二区三区不卡| 国产一区视频在线看| 亚洲一区在线观看免费观看电影高清| 欧美电影在线播放| 精品av久久707| 性欧美video另类hd性玩具| 欧美日韩视频在线一区二区观看视频| 亚洲高清视频在线| 久久精品在线免费观看| 国产乱子伦一区二区三区国色天香 | 国产区精品在线观看| 亚洲午夜小视频| 欧美另类极品videosbest最新版本| 国内免费精品永久在线视频| 亚洲综合欧美日韩| 欧美性久久久| 在线视频免费在线观看一区二区| 欧美高清视频一区二区三区在线观看 | 欧美精品一区二区三区视频| 一区免费视频| 久久综合网络一区二区| 激情久久久久久| 久久精品国产成人| 国产日韩欧美在线看| 亚欧成人精品| 国产女优一区| 午夜久久一区| 国产日韩欧美二区| 欧美制服丝袜第一页| 国产伦一区二区三区色一情| 亚洲专区一区| 国产精品视频一区二区高潮| 亚洲一区二区三区高清不卡| 欧美午夜在线视频| 亚洲图片欧美午夜| 国产精品福利网| 亚洲永久免费| 国产精品每日更新在线播放网址| 亚洲一区久久| 国产精品欧美一区二区三区奶水| 亚洲午夜久久久久久尤物 | 亚洲精品免费看| 欧美精品高清视频| 日韩视频永久免费| 欧美日韩人人澡狠狠躁视频| 99riav1国产精品视频| 欧美日韩视频在线一区二区| 亚洲视频中文| 国产女人aaa级久久久级| 久久精品国产亚洲aⅴ| 激情综合久久| 免费看av成人| 夜久久久久久| 国产精品区免费视频| 欧美一区日韩一区| 国内精品写真在线观看| 玖玖精品视频| 亚洲精品一区久久久久久| 欧美日韩午夜视频在线观看| 亚洲综合激情| 在线播放亚洲一区| 欧美激情亚洲自拍| 亚洲在线中文字幕| 国产午夜久久| 嫩模写真一区二区三区三州| 日韩亚洲成人av在线| 国产精品国产三级国产普通话99| 午夜精品理论片| 激情亚洲网站| 欧美精品在线观看91| 亚洲欧美在线高清| 黄网站色欧美视频| 欧美激情第二页| 亚洲欧美成人精品| 在线电影欧美日韩一区二区私密| 欧美日本一区二区三区| 亚洲天堂免费在线观看视频| 国产日韩精品一区二区三区在线| 玖玖在线精品| 亚洲一区二区三区在线看| 好看不卡的中文字幕| 欧美国产精品久久| 午夜激情综合网| 亚洲国产日韩精品| 国产精品久久久久久久久婷婷| 久久久免费观看视频| 一二三四社区欧美黄| 国产一区二区三区av电影| 欧美激情影院| 久久久av水蜜桃| 一本色道久久88亚洲综合88| 国产一区二区日韩精品| 欧美日韩视频专区在线播放 | 国产精品入口尤物| 欧美va亚洲va国产综合| 亚洲欧美经典视频| 亚洲黄色在线视频| 国产日本欧美在线观看| 欧美乱妇高清无乱码| 久久久国产精品一区二区三区| 99视频一区二区三区| 狠狠色综合日日| 国产精品人人做人人爽| 欧美韩日高清| 久久久久久国产精品mv| 亚洲性夜色噜噜噜7777| 亚洲第一主播视频| 国产女主播视频一区二区| 欧美日韩不卡视频| 老牛嫩草一区二区三区日本| 午夜精品在线观看| 一区二区三区黄色| 亚洲国产精品精华液2区45| 国产精品综合久久久| 欧美日韩不卡视频| 免费久久99精品国产自| 久久精品国产一区二区三区| 亚洲午夜一区二区| 亚洲精品一区中文| 亚洲国产欧美日韩| 韩日欧美一区二区| 国产欧美日韩精品一区| 欧美日韩综合| 欧美久久成人| 欧美福利一区二区| 久久综合伊人77777麻豆| 欧美一区二区精品久久911| 国产精品99久久久久久有的能看| 精品1区2区| 国产一区激情| 国产亚洲精品美女| 国产精品资源| 国产精品久久999| 欧美先锋影音| 欧美人与性禽动交情品| 欧美激情第10页| 麻豆91精品| 久久精品国产欧美亚洲人人爽 | 欧美久久久久中文字幕| 女同一区二区| 免费日韩视频| 蜜臀91精品一区二区三区| 久久国内精品视频| 欧美一区视频在线| 欧美怡红院视频| 性欧美办公室18xxxxhd| 亚洲欧美日韩精品久久久| 亚洲一区亚洲| 亚洲女性裸体视频| 亚洲男人的天堂在线aⅴ视频| 亚洲一区二区三区免费在线观看| 一区二区三区免费网站| 一区二区高清在线| 这里是久久伊人| 亚洲桃色在线一区| 亚洲女爱视频在线| 香蕉久久精品日日躁夜夜躁| 欧美一区在线看| 久久久久久色| 麻豆精品一区二区av白丝在线|