iT邦幫忙

2024 iThome 鐵人賽

DAY 6
0
自我挑戰組

從 Python 開發者的角度學習 Rust —— 從語法基礎到實戰應用系列 第 6

[Day 6] Rust 的流程控制(if, loop, match):與 Python 的對比

  • 分享至 

  • xImage
  •  

流程控制是程式語言中不可或缺的一部分,目的是能夠根據不同的條件來決定程式的執行路徑。Rust 和 Python 在流程控制的處理方式上各有特色,雖然兩者的語法大體相似。在這篇文章中,我們將比較 RustPython 的流程控制,包括 if-elseloop/while/formatch,以幫助 Python 開發者快速掌握 Rust 的流程控制特性。


條件判斷:if 語句

Rust 和 Python 的 if 語句在邏輯上非常相似,主要區別在於 Rust 是一個靜態類別語言,意思是 Rust 的變數在編譯時期就必須被賦予一個具體的類型,並且該類型在整個程式執行期間是不可更改的。這與 Python 這類動態類型語言不同,因為 Python 的變數類型是在程式運行時才會被確定,並且可以根據不同的情況動態改變,因此在條件判斷中,必須使用 bool 類型的值作為條件。

Python 的 if 語句

在 Python 中,if 語句可以根據條件進行分支執行。Python 的 if 語句不要求條件一定是布林值,像 None0、空字串、空列表等都會被當作 False

x = 10

if x > 5:
    print("x 大於 5")
elif x == 5:
    print("x 等於 5")
else:
    print("x 小於 5")

Rust 的 if 語句

Rust 的 if 語句需要條件是 bool 類型,不能像 Python 一樣自動將非布林值轉換為布林值。此外,Rust 的 if 是一個表達式(expression),因此可以直接將 if 語句的結果賦值給變數,這點跟Python是一樣的。

fn main() {
    let x = 10;

    if x > 5 {
        println!("x 大於 5");
    } else if x == 5 {
        println!("x 等於 5");
    } else {
        println!("x 小於 5");
    }

    // 使用 if 表達式
    let y = if x > 5 { "大於 5" } else { "小於或等於 5" };
    println!("y = {}", y);
}

比較:

  • Python:條件可以是任意「真值等價」的對象,例如 None、空列表等。
  • Rust:條件必須是 bool,並且 if 是一個表達式,可以用於賦值。

循環:loopwhilefor

Rust 提供三種循環結構:loopwhilefor。其中,loop 是一個無限循環結構,適合用在需要手動控制循環結束條件的情境下。Python 則沒有類似的 loop 語句,而是依賴 whilefor

1. while 循環

在 Python 和 Rust 中,while 語句的使用幾乎相同,都根據條件來決定是否繼續執行循環。

Python 的 while 語句

x = 0
while x < 5:
    print(x)
    x += 1

Rust 的 while 語句

fn main() {
    let mut x = 0;
    while x < 5 {
        println!("{}", x);
        x += 1;
    }
}

2. loop 語句

Rust 的 loop 是一個無限循環,必須手動使用 break 來終止。

fn main() {
    let mut x = 0;
    loop {
        if x >= 5 {
            break;
        }
        println!("{}", x);
        x += 1;
    }
}

Python 沒有直接對應的無限循環語法,但可以通過 while True 來模擬:

x = 0
while True:
    if x >= 5:
        break
    print(x)
    x += 1

3. for 循環

Python 的 for 語句是用來遍歷一個可迭代對象,而 Rust 的 for 則更像是一個「範圍循環」,用來迭代集合或數列。

Python 的 for 語句

for i in range(5):
    print(i)

Rust 的 for 語句

fn main() {
    for i in 0..5 {
        println!("{}", i);
    }
}

Rust 的 0..5 是一個範圍(Range),表示從 04。需要注意的是,範圍的上限是不包含在內的。

當然,在Rust當中,for迴圈也可以用在可迭代的變數或物件中:

fn main() {
    let numbers = vec![1, 2, 3, 4, 5];  // 定義一個向量

    for num in &numbers {  // 使用 for 迴圈遍歷向量
        println!("{}", num);
    }
}

或者是透過建立迭代器來完成相同的操作

fn main() {
    let numbers = vec![1, 2, 3, 4, 5];

    let iter = numbers.iter();  // 創建迭代器

    for num in iter {
        println!("{}", num);
    }
}

比較:

  • Python:使用 for 循環遍歷可迭代對象(如列表、範圍)。
  • Rust:使用範圍來進行循環,並且提供無限循環的 loop 語句。

模式匹配:match 語句

Rust 的 match 是一個強大且靈活的流程控制工具,用來進行模式匹配。它的功能類似於 Python 的 if-elif 結構,但更加靈活,並且可以同時處理多種模式,但是3.10版本之後的 Python 也有可使用的match語法,所以其實這兩者之間具有相

Python 的 if-elif 語句

首先來看一下Python中的 if-elif 的判斷寫法

x = 2
if x == 1:
    print("One")
elif x == 2:
    print("Two")
else:
    print("Other")

接下來是Python 3.10 版本之後的 match-case 寫法

def get_fruit(fruit):
    match fruit:
        case "apple":
            return "這是一顆蘋果"
        case "banana":
            return "這是一根香蕉"
        case _:
            return "未知水果"

print(get_fruit("apple"))

Rust 的 match 語句

match 可以匹配多種條件,並且還能處理更複雜的模式,如範圍、解構、甚至是 Option 和 Result 類型。

fn get_fruit(fruit: &str) -> &str {
    match fruit {
        "apple" => "這是一顆蘋果",
        "banana" => "這是一根香蕉",
        _ => "未知水果",
    }
}

fn main() {
    println!("{}", get_fruit("apple"));
}

Rust 的 match 具備以下特性:

  1. 完整性檢查:Rust 的 match 要求覆蓋所有可能的條件,因此必須要有一個 _ 或其他方式來匹配所有未列出的條件,否則會出現報錯的情況,而Python的match中沒有加上_,會直接略過其他條件,而不會報錯。
  2. 模式匹配:Rust的match 能夠處理更複雜的模式,如結構體或枚舉的解構,以下進行範例說明:

進階範例:解構與範圍匹配

Rust的match 可以處理範圍和結構體的解構,這是 Python 的無法做到的。

1. 結構體的解構

struct Point {
    x: i32,
    y: i32,
}

fn main() {
    let point = Point { x: 10, y: 5 };

    match point {
        Point { x: 0, y: 0 } => println!("Point at the origin"),
        Point { x, y: 0 } => println!("Point on the x-axis at x = {}", x),
        Point { x: 0, y } => println!("Point on the y-axis at y = {}", y),
        Point { x, y } => println!("Point at ({}, {})", x, y),
    }
}

在這個例子中,我們解構了 Point 結構體,並根據不同的 x 和 y 值進行模式匹配。

2. 枚舉的解構

enum Message {
    Quit,
    Move { x: i32, y: i32 },
    Write(String),
    ChangeColor(i32, i32, i32),
}

fn main() {
    let msg = Message::Move { x: 10, y: 20 };

    match msg {
        Message::Quit => println!("The Quit message"),
        Message::Move { x, y } => println!("Move to coordinates: ({}, {})", x, y),
        Message::Write(text) => println!("Text message: {}", text),
        Message::ChangeColor(r, g, b) => println!("Change color to RGB({}, {}, {})", r, g, b),
    }
}

這個範例展示了如何使用 match 來解構不同變體的枚舉 Message,並根據不同的變體執行對應的邏輯。關於 Rust 的枚舉,將在後續的系列文章當中更加詳細說明,這邊先有一個印象即可。

3. 範圍匹配

fn main() {
    let number = 7;

    match number {
        1..=5 => println!("The number is between 1 and 5"),
        6..=10 => println!("The number is between 6 and 10"),
        _ => println!("The number is outside the range"),
    }
}

這裡使用了範圍匹配來檢查變數 number 是否落在特定的範圍內。

比較:

  • Python:除了可以使用 if-elif 來進行多條件判斷,在3.10版本之後也加入了 match-case 語法,與Rust的match相似,但部分進階匹配方式仍必須使用if-elif完成。
  • Rustmatch 是一個功能強大的模式匹配工具,能處理多種條件與模式,並提供更多靈活性。

總結

Rust 和 Python 在流程控制上有許多相似之處,因此在使用上對於已經有Python撰寫經驗的開發者而言容易上手,嚴格來說,各種條件控制在 Python 跟 Rust 都能完成常用的流程控制設計,只是需要在更熟悉在Rust上的應用,接下來我們就要再講到另一個必修課題了-函數。


上一篇
[Day 5] 深入理解所有權與借用:Rust 的記憶體安全之鑰
下一篇
[Day 7] 函數與方法定義:如何在 Rust 中設計函數
系列文
從 Python 開發者的角度學習 Rust —— 從語法基礎到實戰應用14
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言