Skip to content

从Python到Rust - 2

约 8906 字大约 30 分钟

rustpython

2025-09-17

第4章:控制流与函数

4.1 条件语句

if表达式

Rust中的if是表达式,而不仅仅是语句,这意味着它可以返回值:

// Rust if表达式
fn main() {
    let number = 6;
    
    // 基本if语句
    if number % 4 == 0 {
        println!("number is divisible by 4");
    } else if number % 3 == 0 {
        println!("number is divisible by 3");
    } else if number % 2 == 0 {
        println!("number is divisible by 2");
    } else {
        println!("number is not divisible by 4, 3, or 2");
    }
    
    // if作为表达式
    let condition = true;
    let number = if condition { 5 } else { 6 };
    println!("The value of number is: {}", number);
    
    // 必须返回相同类型
    // let number = if condition { 5 } else { "six" }; // 编译错误
}
# Python if语句
def main():
    number = 6
    
    # 基本if语句
    if number % 4 == 0:
        print("number is divisible by 4")
    elif number % 3 == 0:
        print("number is divisible by 3")
    elif number % 2 == 0:
        print("number is divisible by 2")
    else:
        print("number is not divisible by 4, 3, or 2")
    
    # 三元运算符(条件表达式)
    condition = True
    number = 5 if condition else 6
    print(f"The value of number is: {number}")
    
    # Python允许不同类型
    number = 5 if condition else "six"  # 合法

main()

4.2 循环

loop循环(无限循环)

// Rust无限循环
fn rust_infinite_loop() {
    let mut counter = 0;
    
    let result = loop {
        counter += 1;
        
        if counter == 10 {
            break counter * 2;  // loop可以返回值
        }
    };
    
    println!("The result is {}", result);
}

// 嵌套循环with标签
fn nested_loops() {
    let mut count = 0;
    'counting_up: loop {
        println!("count = {}", count);
        let mut remaining = 10;
        
        loop {
            println!("remaining = {}", remaining);
            if remaining == 9 {
                break;
            }
            if count == 2 {
                break 'counting_up;  // 跳出外层循环
            }
            remaining -= 1;
        }
        
        count += 1;
    }
    println!("End count = {}", count);
}
# Python无限循环
def python_infinite_loop():
    counter = 0
    
    while True:
        counter += 1
        
        if counter == 10:
            result = counter * 2
            break
    
    print(f"The result is {result}")

# Python没有循环标签,需要使用标志变量
def nested_loops():
    count = 0
    should_break = False
    
    while not should_break:
        print(f"count = {count}")
        remaining = 10
        
        while remaining > 0:
            print(f"remaining = {remaining}")
            if remaining == 9:
                break
            if count == 2:
                should_break = True
                break
            remaining -= 1
        
        if not should_break:
            count += 1
    
    print(f"End count = {count}")

while循环

// Rust while循环
fn rust_while_loop() {
    let mut number = 3;
    
    while number != 0 {
        println!("{}!", number);
        number -= 1;
    }
    
    println!("LIFTOFF!!!");
}
# Python while循环
def python_while_loop():
    number = 3
    
    while number != 0:
        print(f"{number}!")
        number -= 1
    
    print("LIFTOFF!!!")

for循环

// Rust for循环
fn rust_for_loops() {
    // 遍历数组
    let a = [10, 20, 30, 40, 50];
    
    for element in a {
        println!("the value is: {}", element);
    }
    
    // 使用范围
    for number in (1..4).rev() {  // rev()反转
        println!("{}!", number);
    }
    println!("LIFTOFF!!!");
    
    // 带索引的遍历
    for (index, value) in a.iter().enumerate() {
        println!("Index: {}, Value: {}", index, value);
    }
    
    // 遍历引用避免所有权转移
    let vec = vec![1, 2, 3, 4, 5];
    for item in &vec {
        println!("item: {}", item);
    }
    println!("vec is still usable: {:?}", vec);
}
# Python for循环
def python_for_loops():
    # 遍历列表
    a = [10, 20, 30, 40, 50]
    
    for element in a:
        print(f"the value is: {element}")
    
    # 使用range
    for number in reversed(range(1, 4)):
        print(f"{number}!")
    print("LIFTOFF!!!")
    
    # 带索引的遍历
    for index, value in enumerate(a):
        print(f"Index: {index}, Value: {value}")
    
    # Python中不需要考虑所有权
    vec = [1, 2, 3, 4, 5]
    for item in vec:
        print(f"item: {item}")
    print(f"vec is still usable: {vec}")

4.3 模式匹配 - match表达式

这是Rust最强大的特性之一,类似Python 3.10+的match语句,但更强大:

基本match用法

// Rust match表达式
fn value_in_cents(coin: Coin) -> u8 {
    match coin {
        Coin::Penny => 1,
        Coin::Nickel => 5,
        Coin::Dime => 10,
        Coin::Quarter => 25,
    }
}

enum Coin {
    Penny,
    Nickel,
    Dime,
    Quarter,
}

fn main() {
    let coin = Coin::Penny;
    println!("Value: {} cents", value_in_cents(coin));
    
    // match必须穷尽所有可能
    let dice_roll = 9;
    match dice_roll {
        3 => add_fancy_hat(),
        7 => remove_fancy_hat(),
        other => move_player(other),  // 捕获其他值
        // _ => (),  // 或者使用_忽略其他值
    }
}

fn add_fancy_hat() {}
fn remove_fancy_hat() {}
fn move_player(num_spaces: u8) {}
# Python match语句(3.10+)
from enum import Enum

class Coin(Enum):
    PENNY = "penny"
    NICKEL = "nickel"
    DIME = "dime"
    QUARTER = "quarter"

def value_in_cents(coin):
    match coin:
        case Coin.PENNY:
            return 1
        case Coin.NICKEL:
            return 5
        case Coin.DIME:
            return 10
        case Coin.QUARTER:
            return 25

def main():
    coin = Coin.PENNY
    print(f"Value: {value_in_cents(coin)} cents")
    
    # Python match不要求穷尽,但建议使用_
    dice_roll = 9
    match dice_roll:
        case 3:
            add_fancy_hat()
        case 7:
            remove_fancy_hat()
        case other:
            move_player(other)

def add_fancy_hat():
    pass

def remove_fancy_hat():
    pass

def move_player(num_spaces):
    pass

main()

匹配Option和Result

// Rust中匹配Option
fn plus_one(x: Option<i32>) -> Option<i32> {
    match x {
        None => None,
        Some(i) => Some(i + 1),
    }
}

fn main() {
    let five = Some(5);
    let six = plus_one(five);
    let none = plus_one(None);
    
    println!("six: {:?}", six);
    println!("none: {:?}", none);
    
    // if let语法糖
    let some_u8_value = Some(0u8);
    if let Some(3) = some_u8_value {
        println!("three");
    }
    
    // while let循环
    let mut stack = Vec::new();
    stack.push(1);
    stack.push(2);
    stack.push(3);
    
    while let Some(top) = stack.pop() {
        println!("{}", top);
    }
}
# Python中处理Optional值
from typing import Optional

def plus_one(x: Optional[int]) -> Optional[int]:
    if x is None:
        return None
    else:
        return x + 1

def main():
    five = 5  # Python没有Option类型
    six = plus_one(five)
    none = plus_one(None)
    
    print(f"six: {six}")
    print(f"none: {none}")
    
    # Python中的条件检查
    some_value = 0
    if some_value == 3:
        print("three")
    
    # Python中的while循环
    stack = [1, 2, 3]
    
    while stack:
        top = stack.pop()
        print(top)

main()

4.4 函数定义与参数

基本函数语法

// Rust函数
fn main() {
    println!("Hello, world!");
    
    another_function(5);
    print_labeled_measurement(5, 'h');
    
    let x = five();
    println!("The value of x is: {}", x);
    
    let x = plus_one(5);
    println!("The value of x is: {}", x);
}

fn another_function(x: i32) {
    println!("The value of x is: {}", x);
}

fn print_labeled_measurement(value: i32, unit_label: char) {
    println!("The measurement is: {}{}", value, unit_label);
}

// 返回值
fn five() -> i32 {
    5  // 表达式,没有分号
}

fn plus_one(x: i32) -> i32 {
    x + 1  // 表达式返回值
}
# Python函数
def main():
    print("Hello, world!")
    
    another_function(5)
    print_labeled_measurement(5, 'h')
    
    x = five()
    print(f"The value of x is: {x}")
    
    x = plus_one(5)
    print(f"The value of x is: {x}")

def another_function(x):
    print(f"The value of x is: {x}")

def print_labeled_measurement(value, unit_label):
    print(f"The measurement is: {value}{unit_label}")

# 返回值
def five():
    return 5

def plus_one(x):
    return x + 1

if __name__ == "__main__":
    main()

高级函数特性

// Rust高级函数特性
fn main() {
    // 函数指针
    let f: fn(i32) -> i32 = add_one;
    println!("Result: {}", f(5));
    
    // 闭包
    let add_two = |x| x + 2;
    println!("Result: {}", add_two(5));
    
    // 高阶函数
    let numbers = vec![1, 2, 3, 4, 5];
    let doubled: Vec<i32> = numbers.iter().map(|x| x * 2).collect();
    println!("Doubled: {:?}", doubled);
    
    // 函数作为参数
    let result = apply_operation(5, 3, add);
    println!("5 + 3 = {}", result);
    
    let result = apply_operation(5, 3, multiply);
    println!("5 * 3 = {}", result);
}

fn add_one(x: i32) -> i32 {
    x + 1
}

fn add(a: i32, b: i32) -> i32 {
    a + b
}

fn multiply(a: i32, b: i32) -> i32 {
    a * b
}

fn apply_operation<F>(a: i32, b: i32, op: F) -> i32
where
    F: Fn(i32, i32) -> i32,
{
    op(a, b)
}
# Python高级函数特性
def main():
    # 函数是第一类对象
    f = add_one
    print(f"Result: {f(5)}")
    
    # Lambda函数
    add_two = lambda x: x + 2
    print(f"Result: {add_two(5)}")
    
    # 高阶函数
    numbers = [1, 2, 3, 4, 5]
    doubled = list(map(lambda x: x * 2, numbers))
    print(f"Doubled: {doubled}")
    
    # 函数作为参数
    result = apply_operation(5, 3, add)
    print(f"5 + 3 = {result}")
    
    result = apply_operation(5, 3, multiply)
    print(f"5 * 3 = {result}")

def add_one(x):
    return x + 1

def add(a, b):
    return a + b

def multiply(a, b):
    return a * b

def apply_operation(a, b, op):
    return op(a, b)

if __name__ == "__main__":
    main()

4.5 闭包 (Closures)

闭包基础

// Rust闭包
fn main() {
    let expensive_closure = |num: u32| -> u32 {
        println!("calculating slowly...");
        std::thread::sleep(std::time::Duration::from_secs(2));
        num
    };
    
    // 类型推断
    let add_one = |x| x + 1;
    println!("Result: {}", add_one(5));
    
    // 捕获环境
    let x = 4;
    let equal_to_x = |z| z == x;  // 捕获x
    let y = 4;
    assert!(equal_to_x(y));
    
    // 移动闭包
    let x = vec![1, 2, 3];
    let equal_to_x = move |z| z == x;  // 移动x的所有权
    // println!("can't use x here: {:?}", x);  // 编译错误
    
    let y = vec![1, 2, 3];
    assert!(equal_to_x(y));
}

// 存储闭包的结构体
struct Cacher<T>
where
    T: Fn(u32) -> u32,
{
    calculation: T,
    value: Option<u32>,
}

impl<T> Cacher<T>
where
    T: Fn(u32) -> u32,
{
    fn new(calculation: T) -> Cacher<T> {
        Cacher {
            calculation,
            value: None,
        }
    }
    
    fn value(&mut self, arg: u32) -> u32 {
        match self.value {
            Some(v) => v,
            None => {
                let v = (self.calculation)(arg);
                self.value = Some(v);
                v
            }
        }
    }
}
# Python闭包
import time
from typing import Callable, Optional

def main():
    def expensive_closure(num: int) -> int:
        print("calculating slowly...")
        time.sleep(2)
        return num
    
    # 简单闭包
    add_one = lambda x: x + 1
    print(f"Result: {add_one(5)}")
    
    # 捕获环境
    x = 4
    def equal_to_x(z):
        return z == x  # 自动捕获x
    
    y = 4
    assert equal_to_x(y)
    
    # Python闭包自动捕获,无需特殊语法
    x = [1, 2, 3]
    def equal_to_x(z):
        return z == x
    
    print(f"can still use x here: {x}")  # Python中x仍然可用
    
    y = [1, 2, 3]
    assert equal_to_x(y)

# 缓存闭包的类
class Cacher:
    def __init__(self, calculation: Callable[[int], int]):
        self.calculation = calculation
        self.value: Optional[int] = None
    
    def get_value(self, arg: int) -> int:
        if self.value is None:
            self.value = self.calculation(arg)
        return self.value

if __name__ == "__main__":
    main()

4.6 迭代器

迭代器基础

// Rust迭代器
fn main() {
    let v1 = vec![1, 2, 3];
    
    // 创建迭代器
    let v1_iter = v1.iter();
    
    // for循环消费迭代器
    for val in v1_iter {
        println!("Got: {}", val);
    }
    
    // 迭代器适配器
    let v1: Vec<i32> = vec![1, 2, 3];
    let v2: Vec<_> = v1.iter().map(|x| x + 1).collect();
    println!("v2: {:?}", v2);
    
    // 使用闭包的迭代器
    let shoes = vec![
        Shoe { size: 10, style: String::from("sneaker") },
        Shoe { size: 13, style: String::from("sandal") },
        Shoe { size: 10, style: String::from("boot") },
    ];
    
    let in_my_size = shoes_in_my_size(shoes, 10);
    println!("Shoes in my size: {:?}", in_my_size);
}

#[derive(PartialEq, Debug)]
struct Shoe {
    size: u32,
    style: String,
}

fn shoes_in_my_size(shoes: Vec<Shoe>, shoe_size: u32) -> Vec<Shoe> {
    shoes.into_iter().filter(|s| s.size == shoe_size).collect()
}

// 自定义迭代器
struct Counter {
    current: usize,
    max: usize,
}

impl Counter {
    fn new(max: usize) -> Counter {
        Counter { current: 0, max }
    }
}

impl Iterator for Counter {
    type Item = usize;
    
    fn next(&mut self) -> Option<Self::Item> {
        if self.current < self.max {
            let current = self.current;
            self.current += 1;
            Some(current)
        } else {
            None
        }
    }
}
# Python迭代器
def main():
    v1 = [1, 2, 3]
    
    # 创建迭代器
    v1_iter = iter(v1)
    
    # for循环消费迭代器
    for val in v1_iter:
        print(f"Got: {val}")
    
    # 使用map和列表推导
    v1 = [1, 2, 3]
    v2 = list(map(lambda x: x + 1, v1))
    # 或者使用列表推导
    v2 = [x + 1 for x in v1]
    print(f"v2: {v2}")
    
    # 使用filter
    shoes = [
        {"size": 10, "style": "sneaker"},
        {"size": 13, "style": "sandal"},
        {"size": 10, "style": "boot"},
    ]
    
    in_my_size = shoes_in_my_size(shoes, 10)
    print(f"Shoes in my size: {in_my_size}")

def shoes_in_my_size(shoes, shoe_size):
    return list(filter(lambda s: s["size"] == shoe_size, shoes))

# 自定义迭代器
class Counter:
    def __init__(self, max_val):
        self.current = 0
        self.max = max_val
    
    def __iter__(self):
        return self
    
    def __next__(self):
        if self.current < self.max:
            current = self.current
            self.current += 1
            return current
        else:
            raise StopIteration

# 使用生成器(更简单的方式)
def counter_generator(max_val):
    current = 0
    while current < max_val:
        yield current
        current += 1

if __name__ == "__main__":
    main()

4.7 实践练习

练习1:斐波那契数列生成器

// Rust版本:斐波那契数列
struct Fibonacci {
    current: u64,
    next: u64,
}

impl Fibonacci {
    fn new() -> Self {
        Fibonacci { current: 0, next: 1 }
    }
}

impl Iterator for Fibonacci {
    type Item = u64;
    
    fn next(&mut self) -> Option<Self::Item> {
        let current = self.current;
        self.current = self.next;
        self.next = current + self.next;
        Some(current)
    }
}

fn fibonacci_recursive(n: u32) -> u64 {
    match n {
        0 => 0,
        1 => 1,
        _ => fibonacci_recursive(n - 1) + fibonacci_recursive(n - 2),
    }
}

fn main() {
    // 使用迭代器
    let fib_seq: Vec<u64> = Fibonacci::new().take(10).collect();
    println!("Fibonacci sequence: {:?}", fib_seq);
    
    // 使用递归
    for i in 0..10 {
        println!("fib({}) = {}", i, fibonacci_recursive(i));
    }
    
    // 使用循环(更高效)
    fn fibonacci_iterative(n: u32) -> u64 {
        match n {
            0 => 0,
            1 => 1,
            _ => {
                let (mut prev, mut current) = (0, 1);
                for _ in 2..=n {
                    let next = prev + current;
                    prev = current;
                    current = next;
                }
                current
            }
        }
    }
    
    for i in 0..10 {
        println!("fib_iter({}) = {}", i, fibonacci_iterative(i));
    }
}
# Python版本:斐波那契数列
class Fibonacci:
    def __init__(self):
        self.current = 0
        self.next = 1
    
    def __iter__(self):
        return self
    
    def __next__(self):
        current = self.current
        self.current = self.next
        self.next = current + self.next
        return current

def fibonacci_recursive(n):
    if n == 0:
        return 0
    elif n == 1:
        return 1
    else:
        return fibonacci_recursive(n - 1) + fibonacci_recursive(n - 2)

def fibonacci_generator():
    """使用生成器的更简洁版本"""
    a, b = 0, 1
    while True:
        yield a
        a, b = b, a + b

def main():
    # 使用迭代器
    fib = Fibonacci()
    fib_seq = [next(fib) for _ in range(10)]
    print(f"Fibonacci sequence: {fib_seq}")
    
    # 使用递归
    for i in range(10):
        print(f"fib({i}) = {fibonacci_recursive(i)}")
    
    # 使用迭代(更高效)
    def fibonacci_iterative(n):
        if n == 0:
            return 0
        elif n == 1:
            return 1
        else:
            prev, current = 0, 1
            for _ in range(2, n + 1):
                prev, current = current, prev + current
            return current
    
    for i in range(10):
        print(f"fib_iter({i}) = {fibonacci_iterative(i)}")
    
    # 使用生成器
    fib_gen = fibonacci_generator()
    fib_seq_gen = [next(fib_gen) for _ in range(10)]
    print(f"Fibonacci from generator: {fib_seq_gen}")

if __name__ == "__main__":
    main()

练习2:数据处理管道

// Rust数据处理管道
fn main() {
    let numbers = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    
    // 函数式处理管道
    let result: Vec<i32> = numbers
        .iter()
        .filter(|&&x| x % 2 == 0)           // 过滤偶数
        .map(|&x| x * x)                    // 平方
        .filter(|&&x| x > 10)               // 过滤大于10的
        .collect();
    
    println!("Processed numbers: {:?}", result);
    
    // 使用自定义函数
    let result2: Vec<i32> = numbers
        .iter()
        .copied()
        .filter(is_even)
        .map(square)
        .filter(|&x| x > 10)
        .collect();
    
    println!("Processed with functions: {:?}", result2);
    
    // 复杂数据处理
    let words = vec!["rust", "python", "javascript", "go", "c++"];
    
    let long_words: Vec<String> = words
        .iter()
        .filter(|word| word.len() > 4)
        .map(|word| word.to_uppercase())
        .collect();
    
    println!("Long words: {:?}", long_words);
}

fn is_even(x: i32) -> bool {
    x % 2 == 0
}

fn square(x: i32) -> i32 {
    x * x
}
# Python数据处理管道
def main():
    numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    
    # 函数式处理管道
    result = list(
        filter(lambda x: x > 10,
            map(lambda x: x * x,
                filter(lambda x: x % 2 == 0, numbers)
            )
        )
    )
    
    # 更Pythonic的方式:列表推导
    result = [x * x for x in numbers if x % 2 == 0 and x * x > 10]
    
    print(f"Processed numbers: {result}")
    
    # 使用自定义函数
    def is_even(x):
        return x % 2 == 0
    
    def square(x):
        return x * x
    
    result2 = [square(x) for x in numbers if is_even(x) and square(x) > 10]
    print(f"Processed with functions: {result2}")
    
    # 复杂数据处理
    words = ["rust", "python", "javascript", "go", "c++"]
    
    long_words = [word.upper() for word in words if len(word) > 4]
    print(f"Long words: {long_words}")

if __name__ == "__main__":
    main()

4.8 本章小结

通过本章学习,你应该掌握:

  1. 控制流:if表达式、循环(loop、while、for)
  2. 模式匹配:match表达式的强大功能
  3. 函数:函数定义、参数传递、返回值
  4. 闭包:捕获环境变量的匿名函数
  5. 迭代器:函数式编程的核心概念

与Python的关键差异:

特性RustPython
if语句表达式,可返回值语句,不返回值
模式匹配必须穷尽,编译时检查可选穷尽,运行时执行
循环标签支持break到外层循环不支持,需要标志变量
闭包需要显式捕获(move)自动捕获
迭代器惰性求值,零成本抽象惰性求值,有运行时开销

下一章预告: 我们将学习Rust的复合数据类型,包括结构体、枚举等。


第5章:复合数据类型

5.1 结构体 (Structs)

结构体让你可以创建比元组更有意义的复合类型:

定义和实例化结构体

// Rust结构体
struct User {
    active: bool,
    username: String,
    email: String,
    sign_in_count: u64,
}

fn main() {
    // 创建实例
    let user1 = User {
        email: String::from("someone@example.com"),
        username: String::from("someusername123"),
        active: true,
        sign_in_count: 1,
    };
    
    // 访问字段
    println!("User email: {}", user1.email);
    
    // 可变实例
    let mut user2 = User {
        email: String::from("another@example.com"),
        username: String::from("anotherusername567"),
        active: true,
        sign_in_count: 1,
    };
    
    user2.email = String::from("anotheremail@example.com");
    
    // 结构体更新语法
    let user3 = User {
        email: String::from("another@example.com"),
        ..user1  // 使用user1的其他字段
    };
    
    // 注意:user1的String字段被移动了,不能再使用
    // println!("{}", user1.username); // 编译错误
    println!("User3 username: {}", user3.username);
}

// 构造函数
fn build_user(email: String, username: String) -> User {
    User {
        email,      // 字段初始化简写
        username,   // 当参数名与字段名相同时
        active: true,
        sign_in_count: 1,
    }
}
# Python类(最接近Rust结构体的概念)
from dataclasses import dataclass
from typing import Optional

@dataclass
class User:
    email: str
    username: str
    active: bool = True
    sign_in_count: int = 1

def main():
    # 创建实例
    user1 = User(
        email="someone@example.com",
        username="someusername123",
        active=True,
        sign_in_count=1
    )
    
    # 访问字段
    print(f"User email: {user1.email}")
    
    # Python对象默认可变
    user2 = User(
        email="another@example.com",
        username="anotherusername567"
    )
    
    user2.email = "anotheremail@example.com"
    
    # Python中的"更新"需要手动处理
    import copy
    user3 = copy.copy(user1)
    user3.email = "another@example.com"
    
    # Python中user1仍然可用
    print(f"User1 still accessible: {user1.username}")
    print(f"User3 username: {user3.username}")

# 构造函数
def build_user(email: str, username: str) -> User:
    return User(
        email=email,
        username=username,
        active=True,
        sign_in_count=1
    )

if __name__ == "__main__":
    main()

元组结构体和单元结构体

// Rust特殊结构体类型
struct Color(i32, i32, i32);
struct Point(i32, i32, i32);

// 单元结构体(类似于空元组)
struct AlwaysEqual;

fn main() {
    let black = Color(0, 0, 0);
    let origin = Point(0, 0, 0);
    
    // 虽然Color和Point有相同的字段,但它们是不同的类型
    // let color: Color = origin; // 编译错误
    
    // 访问元组结构体字段
    println!("Black: ({}, {}, {})", black.0, black.1, black.2);
    
    let subject = AlwaysEqual;
}
# Python中的类似概念
from typing import NamedTuple

class Color(NamedTuple):
    red: int
    green: int
    blue: int

class Point(NamedTuple):
    x: int
    y: int
    z: int

class AlwaysEqual:
    """空类,类似单元结构体"""
    pass

def main():
    black = Color(0, 0, 0)
    origin = Point(0, 0, 0)
    
    # Python中可以直接赋值(类型检查器会警告)
    # color = origin  # 类型不匹配,但运行时不报错
    
    # 访问字段
    print(f"Black: ({black.red}, {black.green}, {black.blue})")
    # 或者使用索引(对于NamedTuple)
    print(f"Black: ({black[0]}, {black[1]}, {black[2]})")
    
    subject = AlwaysEqual()

if __name__ == "__main__":
    main()

5.2 方法语法

定义方法

// Rust方法定义
#[derive(Debug)]
struct Rectangle {
    width: u32,
    height: u32,
}

impl Rectangle {
    // 方法(需要self参数)
    fn area(&self) -> u32 {
        self.width * self.height
    }
    
    fn can_hold(&self, other: &Rectangle) -> bool {
        self.width > other.width && self.height > other.height
    }
    
    // 关联函数(不需要self参数,类似静态方法)
    fn square(size: u32) -> Rectangle {
        Rectangle {
            width: size,
            height: size,
        }
    }
    
    // 可变引用方法
    fn double_size(&mut self) {
        self.width *= 2;
        self.height *= 2;
    }
}

fn main() {
    let rect1 = Rectangle {
        width: 30,
        height: 50,
    };
    
    let rect2 = Rectangle {
        width: 10,
        height: 40,
    };
    
    let rect3 = Rectangle {
        width: 60,
        height: 45,
    };
    
    println!("Area of rect1: {}", rect1.area());
    println!("Can rect1 hold rect2? {}", rect1.can_hold(&rect2));
    println!("Can rect1 hold rect3? {}", rect1.can_hold(&rect3));
    
    // 关联函数调用
    let square = Rectangle::square(20);
    println!("Square: {:?}", square);
    
    // 可变方法
    let mut rect4 = Rectangle {
        width: 10,
        height: 10,
    };
    
    println!("Before: {:?}", rect4);
    rect4.double_size();
    println!("After: {:?}", rect4);
}
# Python类方法
class Rectangle:
    def __init__(self, width: int, height: int):
        self.width = width
        self.height = height
    
    def __repr__(self):
        return f"Rectangle(width={self.width}, height={self.height})"
    
    # 实例方法
    def area(self) -> int:
        return self.width * self.height
    
    def can_hold(self, other: 'Rectangle') -> bool:
        return self.width > other.width and self.height > other.height
    
    # 类方法(类似关联函数)
    @classmethod
    def square(cls, size: int) -> 'Rectangle':
        return cls(size, size)
    
    # Python中所有方法都可以修改对象
    def double_size(self):
        self.width *= 2
        self.height *= 2

def main():
    rect1 = Rectangle(30, 50)
    rect2 = Rectangle(10, 40)
    rect3 = Rectangle(60, 45)
    
    print(f"Area of rect1: {rect1.area()}")
    print(f"Can rect1 hold rect2? {rect1.can_hold(rect2)}")
    print(f"Can rect1 hold rect3? {rect1.can_hold(rect3)}")
    
    # 类方法调用
    square = Rectangle.square(20)
    print(f"Square: {square}")
    
    # 修改方法
    rect4 = Rectangle(10, 10)
    print(f"Before: {rect4}")
    rect4.double_size()
    print(f"After: {rect4}")

if __name__ == "__main__":
    main()

5.3 枚举 (Enums)

枚举让你可以列举一个类型的所有可能值:

基本枚举

// Rust枚举
enum IpAddrKind {
    V4,
    V6,
}

// 带数据的枚举
enum IpAddr {
    V4(u8, u8, u8, u8),
    V6(String),
}

// 复杂枚举
enum Message {
    Quit,
    Move { x: i32, y: i32 },
    Write(String),
    ChangeColor(i32, i32, i32),
}

impl Message {
    fn call(&self) {
        match self {
            Message::Quit => println!("Quit"),
            Message::Move { x, y } => println!("Move to ({}, {})", x, y),
            Message::Write(text) => println!("Write: {}", text),
            Message::ChangeColor(r, g, b) => println!("Change color to ({}, {}, {})", r, g, b),
        }
    }
}

fn main() {
    let four = IpAddrKind::V4;
    let six = IpAddrKind::V6;
    
    route(four);
    route(six);
    
    let home = IpAddr::V4(127, 0, 0, 1);
    let loopback = IpAddr::V6(String::from("::1"));
    
    let m = Message::Write(String::from("hello"));
    m.call();
    
    let m2 = Message::Move { x: 10, y: 20 };
    m2.call();
}

fn route(ip_kind: IpAddrKind) {
    match ip_kind {
        IpAddrKind::V4 => println!("IPv4"),
        IpAddrKind::V6 => println!("IPv6"),
    }
}
# Python枚举
from enum import Enum, auto
from typing import Union, Tuple
from dataclasses import dataclass

class IpAddrKind(Enum):
    V4 = auto()
    V6 = auto()

# Python需要使用Union类型或继承来模拟带数据的枚举
@dataclass
class IPv4:
    octets: Tuple[int, int, int, int]

@dataclass
class IPv6:
    address: str

IpAddr = Union[IPv4, IPv6]

# 复杂枚举需要使用类继承
class Message:
    def call(self):
        if isinstance(self, Quit):
            print("Quit")
        elif isinstance(self, Move):
            print(f"Move to ({self.x}, {self.y})")
        elif isinstance(self, Write):
            print(f"Write: {self.text}")
        elif isinstance(self, ChangeColor):
            print(f"Change color to ({self.r}, {self.g}, {self.b})")

class Quit(Message):
    pass

@dataclass
class Move(Message):
    x: int
    y: int

@dataclass
class Write(Message):
    text: str

@dataclass
class ChangeColor(Message):
    r: int
    g: int
    b: int

def main():
    four = IpAddrKind.V4
    six = IpAddrKind.V6
    
    route(four)
    route(six)
    
    home = IPv4((127, 0, 0, 1))
    loopback = IPv6("::1")
    
    m = Write("hello")
    m.call()
    
    m2 = Move(10, 20)
    m2.call()

def route(ip_kind: IpAddrKind):
    if ip_kind == IpAddrKind.V4:
        print("IPv4")
    elif ip_kind == IpAddrKind.V6:
        print("IPv6")

if __name__ == "__main__":
    main()

5.4 Option枚举

Option是Rust标准库中最重要的枚举之一:

// Rust Option枚举
fn main() {
    let some_number = Some(5);
    let some_string = Some("a string");
    let absent_number: Option<i32> = None;
    
    // 使用match处理Option
    let x: i8 = 5;
    let y: Option<i8> = Some(5);
    
    let sum = match y {
        Some(value) => x + value,
        None => x,
    };
    
    println!("Sum: {}", sum);
    
    // 使用if let简化
    if let Some(value) = y {
        println!("y has value: {}", value);
    }
    
    // Option的常用方法
    let number = Some(42);
    
    // unwrap: 如果是Some则返回值,如果是None则panic
    println!("Number: {}", number.unwrap());
    
    // unwrap_or: 如果是None则返回默认值
    let none_number: Option<i32> = None;
    println!("Number or default: {}", none_number.unwrap_or(0));
    
    // map: 对Some中的值进行变换
    let doubled = number.map(|x| x * 2);
    println!("Doubled: {:?}", doubled);
    
    // and_then: 链式操作
    let result = number
        .map(|x| x * 2)
        .and_then(|x| if x > 50 { Some(x) } else { None });
    
    println!("Chained result: {:?}", result);
}
# Python Optional类型
from typing import Optional

def main():
    # Python使用None表示缺失值
    some_number: Optional[int] = 5
    some_string: Optional[str] = "a string"
    absent_number: Optional[int] = None
    
    # Python中需要显式检查None
    x = 5
    y: Optional[int] = 5
    
    if y is not None:
        sum_val = x + y
    else:
        sum_val = x
    
    print(f"Sum: {sum_val}")
    
    # 使用海象操作符(Python 3.8+)
    if (value := y) is not None:
        print(f"y has value: {value}")
    
    # Python没有unwrap,但可以直接访问(可能出错)
    number: Optional[int] = 42
    if number is not None:
        print(f"Number: {number}")
    
    # 使用or提供默认值
    none_number: Optional[int] = None
    print(f"Number or default: {none_number or 0}")
    
    # 使用map需要自定义函数
    def optional_map(opt_val, func):
        return func(opt_val) if opt_val is not None else None
    
    doubled = optional_map(number, lambda x: x * 2)
    print(f"Doubled: {doubled}")
    
    # 链式操作需要手动处理
    result = number
    if result is not None:
        result = result * 2
        if result <= 50:
            result = None
    
    print(f"Chained result: {result}")

if __name__ == "__main__":
    main()

5.5 实践练习

练习1:构建一个简单的形状计算器

// Rust形状计算器
#[derive(Debug)]
enum Shape {
    Circle { radius: f64 },
    Rectangle { width: f64, height: f64 },
    Triangle { base: f64, height: f64 },
}

impl Shape {
    fn area(&self) -> f64 {
        match self {
            Shape::Circle { radius } => std::f64::consts::PI * radius * radius,
            Shape::Rectangle { width, height } => width * height,
            Shape::Triangle { base, height } => 0.5 * base * height,
        }
    }
    
    fn perimeter(&self) -> f64 {
        match self {
            Shape::Circle { radius } => 2.0 * std::f64::consts::PI * radius,
            Shape::Rectangle { width, height } => 2.0 * (width + height),
            Shape::Triangle { base, height } => {
                // 假设是等腰三角形
                let side = (height * height + (base / 2.0) * (base / 2.0)).sqrt();
                base + 2.0 * side
            }
        }
    }
}

fn main() {
    let shapes = vec![
        Shape::Circle { radius: 5.0 },
        Shape::Rectangle { width: 10.0, height: 20.0 },
        Shape::Triangle { base: 8.0, height: 6.0 },
    ];
    
    for shape in &shapes {
        println!("{:?}", shape);
        println!("Area: {:.2}", shape.area());
        println!("Perimeter: {:.2}", shape.perimeter());
        println!("---");
    }
    
    // 计算总面积
    let total_area: f64 = shapes.iter().map(|shape| shape.area()).sum();
    println!("Total area: {:.2}", total_area);
}
# Python形状计算器
import math
from abc import ABC, abstractmethod
from typing import List

class Shape(ABC):
    @abstractmethod
    def area(self) -> float:
        pass
    
    @abstractmethod
    def perimeter(self) -> float:
        pass

class Circle(Shape):
    def __init__(self, radius: float):
        self.radius = radius
    
    def area(self) -> float:
        return math.pi * self.radius ** 2
    
    def perimeter(self) -> float:
        return 2 * math.pi * self.radius
    
    def __repr__(self):
        return f"Circle(radius={self.radius})"

class Rectangle(Shape):
    def __init__(self, width: float, height: float):
        self.width = width
        self.height = height
    
    def area(self) -> float:
        return self.width * self.height
    
    def perimeter(self) -> float:
        return 2 * (self.width + self.height)
    
    def __repr__(self):
        return f"Rectangle(width={self.width}, height={self.height})"

class Triangle(Shape):
    def __init__(self, base: float, height: float):
        self.base = base
        self.height = height
    
    def area(self) -> float:
        return 0.5 * self.base * self.height
    
    def perimeter(self) -> float:
        # 假设是等腰三角形
        side = math.sqrt(self.height ** 2 + (self.base / 2) ** 2)
        return self.base + 2 * side
    
    def __repr__(self):
        return f"Triangle(base={self.base}, height={self.height})"

def main():
    shapes: List[Shape] = [
        Circle(5.0),
        Rectangle(10.0, 20.0),
        Triangle(8.0, 6.0),
    ]
    
    for shape in shapes:
        print(shape)
        print(f"Area: {shape.area():.2f}")
        print(f"Perimeter: {shape.perimeter():.2f}")
        print("---")
    
    # 计算总面积
    total_area = sum(shape.area() for shape in shapes)
    print(f"Total area: {total_area:.2f}")

if __name__ == "__main__":
    main()

练习2:构建一个简单的库存管理系统

// Rust库存管理系统
use std::collections::HashMap;

#[derive(Debug, Clone)]
struct Product {
    id: u32,
    name: String,
    price: f64,
    quantity: u32,
}

impl Product {
    fn new(id: u32, name: String, price: f64, quantity: u32) -> Self {
        Product { id, name, price, quantity }
    }
    
    fn total_value(&self) -> f64 {
        self.price * self.quantity as f64
    }
    
    fn is_low_stock(&self, threshold: u32) -> bool {
        self.quantity < threshold
    }
}

struct Inventory {
    products: HashMap<u32, Product>,
}

impl Inventory {
    fn new() -> Self {
        Inventory {
            products: HashMap::new(),
        }
    }
    
    fn add_product(&mut self, product: Product) {
        self.products.insert(product.id, product);
    }
    
    fn update_quantity(&mut self, id: u32, new_quantity: u32) -> Option<&Product> {
        if let Some(product) = self.products.get_mut(&id) {
            product.quantity = new_quantity;
            Some(product)
        } else {
            None
        }
    }
    
    fn get_product(&self, id: u32) -> Option<&Product> {
        self.products.get(&id)
    }
    
    fn total_inventory_value(&self) -> f64 {
        self.products.values().map(|p| p.total_value()).sum()
    }
    
    fn low_stock_products(&self, threshold: u32) -> Vec<&Product> {
        self.products
            .values()
            .filter(|p| p.is_low_stock(threshold))
            .collect()
    }
}

fn main() {
    let mut inventory = Inventory::new();
    
    // 添加产品
    inventory.add_product(Product::new(1, "Laptop".to_string(), 999.99, 10));
    inventory.add_product(Product::new(2, "Mouse".to_string(), 29.99, 5));
    inventory.add_product(Product::new(3, "Keyboard".to_string(), 79.99, 2));
    
    // 查看产品
    if let Some(laptop) = inventory.get_product(1) {
        println!("Found laptop: {:?}", laptop);
        println!("Total value: ${:.2}", laptop.total_value());
    }
    
    // 更新数量
    inventory.update_quantity(2, 50);
    
    // 计算总库存价值
    println!("Total inventory value: ${:.2}", inventory.total_inventory_value());
    
    // 查找低库存产品
    let low_stock = inventory.low_stock_products(10);
    println!("Low stock products:");
    for product in low_stock {
        println!("  {:?}", product);
    }
}
# Python库存管理系统
from typing import Dict, List, Optional

class Product:
    def __init__(self, id: int, name: str, price: float, quantity: int):
        self.id = id
        self.name = name
        self.price = price
        self.quantity = quantity
    
    def total_value(self) -> float:
        return self.price * self.quantity
    
    def is_low_stock(self, threshold: int) -> bool:
        return self.quantity < threshold
    
    def __repr__(self):
        return f"Product(id={self.id}, name='{self.name}', price={self.price}, quantity={self.quantity})"

class Inventory:
    def __init__(self):
        self.products: Dict[int, Product] = {}
    
    def add_product(self, product: Product):
        self.products[product.id] = product
    
    def update_quantity(self, id: int, new_quantity: int) -> Optional[Product]:
        if id in self.products:
            self.products[id].quantity = new_quantity
            return self.products[id]
        return None
    
    def get_product(self, id: int) -> Optional[Product]:
        return self.products.get(id)
    
    def total_inventory_value(self) -> float:
        return sum(product.total_value() for product in self.products.values())
    
    def low_stock_products(self, threshold: int) -> List[Product]:
        return [product for product in self.products.values() 
                if product.is_low_stock(threshold)]

def main():
    inventory = Inventory()
    
    # 添加产品
    inventory.add_product(Product(1, "Laptop", 999.99, 10))
    inventory.add_product(Product(2, "Mouse", 29.99, 5))
    inventory.add_product(Product(3, "Keyboard", 79.99, 2))
    
    # 查看产品
    laptop = inventory.get_product(1)
    if laptop:
        print(f"Found laptop: {laptop}")
        print(f"Total value: ${laptop.total_value():.2f}")
    
    # 更新数量
    inventory.update_quantity(2, 50)
    
    # 计算总库存价值
    print(f"Total inventory value: ${inventory.total_inventory_value():.2f}")
    
    # 查找低库存产品
    low_stock = inventory.low_stock_products(10)
    print("Low stock products:")
    for product in low_stock:
        print(f"  {product}")

if __name__ == "__main__":
    main()

5.6 本章小结

通过本章学习,你应该掌握:

  1. 结构体:定义自定义数据类型,组织相关数据
  2. 方法:为结构体添加行为,关联函数
  3. 枚举:定义可能值的有限集合,强大的模式匹配
  4. Option类型:安全地处理可能不存在的值

与Python的关键差异:

特性RustPython
结构体编译时类型检查,所有权语义运行时类型,引用语义
方法需要显式self参数类型默认可变self
枚举可携带数据,强制匹配简单值,可选匹配
空值处理Option类型,编译时安全None值,运行时检查

下一章预告: 我们将学习Rust的错误处理机制,包括Result类型和错误传播。


第6章:错误处理

6.1 Rust的错误处理哲学

Rust将错误分为两大类:可恢复错误和不可恢复错误。这与Python的异常机制有根本不同:

  • 可恢复错误:如文件未找到,用Result<T, E>处理
  • 不可恢复错误:如数组越界,用panic!处理

Python vs Rust错误处理对比

# Python使用异常处理所有错误
def read_file(filename):
    try:
        with open(filename, 'r') as f:
            return f.read()
    except FileNotFoundError:
        print(f"File {filename} not found")
        return None
    except IOError as e:
        print(f"Error reading file: {e}")
        return None

def divide(a, b):
    try:
        return a / b
    except ZeroDivisionError:
        print("Cannot divide by zero")
        return None
// Rust使用Result处理可恢复错误
use std::fs;
use std::io;

fn read_file(filename: &str) -> Result<String, io::Error> {
    fs::read_to_string(filename)
}

fn divide(a: f64, b: f64) -> Result<f64, String> {
    if b == 0.0 {
        Err("Cannot divide by zero".to_string())
    } else {
        Ok(a / b)
    }
}

fn main() {
    // 处理文件读取错误
    match read_file("hello.txt") {
        Ok(contents) => println!("File contents: {}", contents),
        Err(error) => println!("Error reading file: {}", error),
    }
    
    // 处理除法错误
    match divide(10.0, 0.0) {
        Ok(result) => println!("Result: {}", result),
        Err(error) => println!("Error: {}", error),
    }
}

6.2 panic! - 不可恢复错误

panic!基础

// Rust panic!示例
fn main() {
    // 显式panic
    // panic!("crash and burn");
    
    // 数组越界会导致panic
    let v = vec![1, 2, 3];
    // v[99]; // 这会panic
    
    // 安全的数组访问
    match v.get(99) {
        Some(value) => println!("Value: {}", value),
        None => println!("Index out of bounds"),
    }
    
    // 设置panic时的行为
    // 在Cargo.toml中设置:
    // [profile.release]
    // panic = 'abort'  // 直接终止而不是展开栈
}

fn might_panic(should_panic: bool) {
    if should_panic {
        panic!("This function panicked!");
    }
    println!("No panic occurred");
}
# Python异常机制
def main():
    # Python中的异常
    try:
        # raise Exception("crash and burn")
        pass
    except Exception as e:
        print(f"Caught exception: {e}")
    
    # 列表越界抛出异常
    v = [1, 2, 3]
    try:
        print(v[99])  # 抛出IndexError
    except IndexError:
        print("Index out of bounds")
    
    # 安全的访问方式
    if 99 < len(v):
        print(f"Value: {v[99]}")
    else:
        print("Index out of bounds")

def might_raise(should_raise):
    if should_raise:
        raise Exception("This function raised an exception!")
    print("No exception occurred")

if __name__ == "__main__":
    main()

6.3 Result<T, E> - 可恢复错误

Result基础

// Rust Result类型
use std::fs::File;
use std::io::ErrorKind;

fn main() {
    // 基本Result处理
    let greeting_file_result = File::open("hello.txt");
    
    let greeting_file = match greeting_file_result {
        Ok(file) => file,
        Err(error) => match error.kind() {
            ErrorKind::NotFound => match File::create("hello.txt") {
                Ok(fc) => fc,
                Err(e) => panic!("Problem creating the file: {:?}", e),
            },
            other_error => {
                panic!("Problem opening the file: {:?}", other_error);
            }
        },
    };
    
    // 使用unwrap_or_else简化
    let greeting_file = File::open("hello.txt").unwrap_or_else(|error| {
        if error.kind() == ErrorKind::NotFound {
            File::create("hello.txt").unwrap_or_else(|error| {
                panic!("Problem creating the file: {:?}", error);
            })
        } else {
            panic!("Problem opening the file: {:?}", error);
        }
    });
}

// 自定义Result类型
#[derive(Debug)]
enum MathError {
    DivisionByZero,
    NegativeSquareRoot,
}

fn safe_divide(a: f64, b: f64) -> Result<f64, MathError> {
    if b == 0.0 {
        Err(MathError::DivisionByZero)
    } else {
        Ok(a / b)
    }
}

fn safe_sqrt(x: f64) -> Result<f64, MathError> {
    if x < 0.0 {
        Err(MathError::NegativeSquareRoot)
    } else {
        Ok(x.sqrt())
    }
}
# Python自定义异常
class MathError(Exception):
    pass

class DivisionByZeroError(MathError):
    pass

class NegativeSquareRootError(MathError):
    pass

def safe_divide(a, b):
    if b == 0:
        raise DivisionByZeroError("Cannot divide by zero")
    return a / b

def safe_sqrt(x):
    if x < 0:
        raise NegativeSquareRootError("Cannot take square root of negative number")
    return x ** 0.5

def main():
    # 文件操作
    try:
        with open("hello.txt", 'r') as f:
            content = f.read()
    except FileNotFoundError:
        try:
            with open("hello.txt", 'w') as f:
                f.write("")
            print("Created new file")
        except IOError as e:
            print(f"Problem creating file: {e}")
    except IOError as e:
        print(f"Problem opening file: {e}")
    
    # 数学操作
    try:
        result = safe_divide(10, 0)
        print(f"Division result: {result}")
    except DivisionByZeroError as e:
        print(f"Math error: {e}")
    
    try:
        result = safe_sqrt(-1)
        print(f"Square root result: {result}")
    except NegativeSquareRootError as e:
        print(f"Math error: {e}")

if __name__ == "__main__":
    main()

6.4 unwrap和expect

错误处理的快捷方式

// Rust unwrap和expect
use std::fs::File;

fn main() {
    // unwrap: 如果是Ok则返回值,如果是Err则panic
    let greeting_file = File::open("hello.txt").unwrap();
    
    // expect: 类似unwrap,但可以自定义panic消息
    let greeting_file = File::open("hello.txt")
        .expect("hello.txt should be included in this project");
    
    // 更安全的方式:使用if let
    if let Ok(file) = File::open("hello.txt") {
        println!("File opened successfully");
    } else {
        println!("Failed to open file");
    }
    
    // 或者使用match
    match File::open("hello.txt") {
        Ok(file) => println!("File opened: {:?}", file),
        Err(error) => println!("Failed to open file: {}", error),
    }
    
    // Result的其他有用方法
    let result: Result<i32, &str> = Ok(42);
    
    // is_ok和is_err
    if result.is_ok() {
        println!("Result is ok");
    }
    
    // unwrap_or: 提供默认值
    let value = result.unwrap_or(0);
    println!("Value: {}", value);
    
    // map: 变换Ok值
    let doubled = result.map(|x| x * 2);
    println!("Doubled: {:?}", doubled);
    
    // map_err: 变换Err值
    let result_with_mapped_error = result.map_err(|e| format!("Error: {}", e));
    println!("Mapped error: {:?}", result_with_mapped_error);
}
# Python没有直接等价物,但可以创建类似功能
def unwrap(result, default_exception=None):
    """模拟Rust的unwrap"""
    if isinstance(result, Exception):
        if default_exception:
            raise default_exception
        else:
            raise result
    return result

def expect(result, message):
    """模拟Rust的expect"""
    if isinstance(result, Exception):
        raise Exception(message)
    return result

def main():
    # Python中通常直接处理异常
    try:
        with open("hello.txt", 'r') as f:
            content = f.read()
        print("File opened successfully")
    except FileNotFoundError:
        print("Failed to open file")
    
    # 模拟Result行为
    def safe_operation():
        try:
            with open("hello.txt", 'r') as f:
                return f.read()
        except FileNotFoundError as e:
            return e
    
    result = safe_operation()
    
    # 检查是否为异常
    if isinstance(result, Exception):
        print("Operation failed")
    else:
        print(f"Operation succeeded: {result}")
    
    # 使用默认值
    def get_value_or_default(operation, default):
        try:
            return operation()
        except:
            return default
    
    value = get_value_or_default(lambda: int("not_a_number"), 0)
    print(f"Value: {value}")

if __name__ == "__main__":
    main()

6.5 错误传播 - ? 操作符

? 操作符简化错误传播

// Rust错误传播
use std::fs::File;
use std::io::{self, Read};

// 传统的错误传播方式
fn read_username_from_file_verbose() -> Result<String, io::Error> {
    let username_file_result = File::open("hello.txt");
    
    let mut username_file = match username_file_result {
        Ok(file) => file,
        Err(e) => return Err(e),
    };
    
    let mut username = String::new();
    
    match username_file.read_to_string(&mut username) {
        Ok(_) => Ok(username),
        Err(e) => Err(e),
    }
}

// 使用?操作符简化
fn read_username_from_file() -> Result<String, io::Error> {
    let mut username_file = File::open("hello.txt")?;
    let mut username = String::new();
    username_file.read_to_string(&mut username)?;
    Ok(username)
}

// 进一步简化
fn read_username_from_file_short() -> Result<String, io::Error> {
    let mut username = String::new();
    File::open("hello.txt")?.read_to_string(&mut username)?;
    Ok(username)
}

// 最简化(使用标准库函数)
fn read_username_from_file_shortest() -> Result<String, io::Error> {
    std::fs::read_to_string("hello.txt")
}

// ?操作符也可以用于Option
fn last_char_of_first_line(text: &str) -> Option<char> {
    text.lines().next()?.chars().last()
}

fn main() {
    match read_username_from_file() {
        Ok(username) => println!("Username: {}", username),
        Err(error) => println!("Error: {}", error),
    }
    
    let text = "Hello\nWorld";
    match last_char_of_first_line(text) {
        Some(ch) => println!("Last char: {}", ch),
        None => println!("No last char found"),
    }
}
# Python异常传播
def read_username_from_file_verbose():
    """传统的异常处理方式"""
    try:
        username_file = open("hello.txt", 'r')
    except IOError as e:
        raise e
    
    try:
        username = username_file.read()
        username_file.close()
        return username
    except IOError as e:
        username_file.close()
        raise e

def read_username_from_file():
    """Python的惯用方式"""
    with open("hello.txt", 'r') as f:
        return f.read()

def read_username_from_file_with_handling():
    """带错误处理的版本"""
    try:
        with open("hello.txt", 'r') as f:
            return f.read()
    except FileNotFoundError:
        raise FileNotFoundError("Username file not found")
    except IOError as e:
        raise IOError(f"Error reading username file: {e}")

# Python没有直接等价的?操作符,但可以用装饰器模拟
def propagate_none(func):
    """装饰器:如果任何中间步骤返回None,则返回None"""
    def wrapper(*args, **kwargs):
        try:
            return func(*args, **kwargs)
        except (AttributeError, TypeError):
            return None
    return wrapper

@propagate_none
def last_char_of_first_line(text):
    return text.split('\n')[0][-1] if text and '\n' in text else text[-1] if text else None

def last_char_of_first_line_safe(text):
    """更安全的版本"""
    if not text:
        return None
    
    lines = text.split('\n')
    if not lines:
        return None
    
    first_line = lines[0]
    if not first_line:
        return None
    
    return first_line[-1]

def main():
    try:
        username = read_username_from_file()
        print(f"Username: {username}")
    except IOError as error:
        print(f"Error: {error}")
    
    text = "Hello\nWorld"
    last_char = last_char_of_first_line_safe(text)
    if last_char:
        print(f"Last char: {last_char}")
    else:
        print("No last char found")

if __name__ == "__main__":
    main()

6.6 自定义错误类型

创建和使用自定义错误

// Rust自定义错误类型
use std::fmt;
use std::error::Error;

#[derive(Debug)]
enum CalculatorError {
    DivisionByZero,
    InvalidInput(String),
    Overflow,
}

impl fmt::Display for CalculatorError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            CalculatorError::DivisionByZero => write!(f, "Division by zero"),
            CalculatorError::InvalidInput(msg) => write!(f, "Invalid input: {}", msg),
            CalculatorError::Overflow => write!(f, "Calculation overflow"),
        }
    }
}

impl Error for CalculatorError {}

struct Calculator;

impl Calculator {
    fn divide(a: f64, b: f64) -> Result<f64, CalculatorError> {
        if b == 0.0 {
            Err(CalculatorError::DivisionByZero)
        } else {
            let result = a / b;
            if result.is_infinite() {
                Err(CalculatorError::Overflow)
            } else {
                Ok(result)
            }
        }
    }
    
    fn parse_and_add(a: &str, b: &str) -> Result<f64, CalculatorError> {
        let num_a = a.parse::<f64>()
            .map_err(|_| CalculatorError::InvalidInput(format!("'{}' is not a number", a)))?;
        let num_b = b.parse::<f64>()
            .map_err(|_| CalculatorError::InvalidInput(format!("'{}' is not a number", b)))?;
        
        let result = num_a + num_b;
        if result.is_infinite() {
            Err(CalculatorError::Overflow)
        } else {
            Ok(result)
        }
    }
}

// 错误转换
#[derive(Debug)]
enum AppError {
    Calculator(CalculatorError),
    Io(std::io::Error),
}

impl fmt::Display for AppError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            AppError::Calculator(err) => write!(f, "Calculator error: {}", err),
            AppError::Io(err) => write!(f, "IO error: {}", err),
        }
    }
}

impl Error for AppError {}

impl From<CalculatorError> for AppError {
    fn from(err: CalculatorError) -> AppError {
        AppError::Calculator(err)
    }
}

impl From<std::io::Error> for AppError {
    fn from(err: std::io::Error) -> AppError {
        AppError::Io(err)
    }
}

fn main() {
    // 测试除法
    match Calculator::divide(10.0, 0.0) {
        Ok(result) => println!("Division result: {}", result),
        Err(error) => println!("Error: {}", error),
    }
    
    // 测试解析和加法
    match Calculator::parse_and_add("10", "abc") {
        Ok(result) => println!("Addition result: {}", result),
        Err(error) => println!("Error: {}", error),
    }
    
    // 使用?操作符进行错误转换
    fn do_calculation() -> Result<f64, AppError> {
        let result = Calculator::parse_and_add("10", "20")?; // 自动转换
        Ok(result * 2.0)
    }
    
    match do_calculation() {
        Ok(result) => println!("Final result: {}", result),
        Err(error) => println!("Application error: {}", error),
    }
}
# Python自定义异常类型
class CalculatorError(Exception):
    """计算器基础异常"""
    pass

class DivisionByZeroError(CalculatorError):
    """除零异常"""
    def __init__(self):
        super().__init__("Division by zero")

class InvalidInputError(CalculatorError):
    """无效输入异常"""
    def __init__(self, message):
        super().__init__(f"Invalid input: {message}")

class OverflowError(CalculatorError):
    """溢出异常"""
    def __init__(self):
        super().__init__("Calculation overflow")

class Calculator:
    @staticmethod
    def divide(a, b):
        if b == 0:
            raise DivisionByZeroError()
        
        result = a / b
        if not (-float('inf') < result < float('inf')):
            raise OverflowError()
        
        return result
    
    @staticmethod
    def parse_and_add(a_str, b_str):
        try:
            num_a = float(a_str)
        except ValueError:
            raise InvalidInputError(f"'{a_str}' is not a number")
        
        try:
            num_b = float(b_str)
        except ValueError:
            raise InvalidInputError(f"'{b_str}' is not a number")
        
        result = num_a + num_b
        if not (-float('inf') < result < float('inf')):
            raise OverflowError()
        
        return result

# 异常包装
class AppError(Exception):
    """应用程序错误包装器"""
    def __init__(self, original_error):
        self.original_error = original_error
        super().__init__(f"Application error: {original_error}")

def main():
    # 测试除法
    try:
        result = Calculator.divide(10.0, 0.0)
        print(f"Division result: {result}")
    except CalculatorError as error:
        print(f"Error: {error}")
    
    # 测试解析和加法
    try:
        result = Calculator.parse_and_add("10", "abc")
        print(f"Addition result: {result}")
    except CalculatorError as error:
        print(f"Error: {error}")
    
    # 异常包装
    def do_calculation():
        try:
            result = Calculator.parse_and_add("10", "20")
            return result * 2.0
        except CalculatorError as e:
            raise AppError(e)
        except IOError as e:
            raise AppError(e)
    
    try:
        result = do_calculation()
        print(f"Final result: {result}")
    except AppError as error:
        print(f"Application error: {error}")

if __name__ == "__main__":
    main()

6.7 实践练习

练习1:文件处理器

// Rust文件处理器
use std::fs;
use std::io;
use std::path::Path;

#[derive(Debug)]
enum FileProcessorError {
    FileNotFound(String),
    PermissionDenied(String),
    InvalidFormat(String),
    IoError(io::Error),
}

impl std::fmt::Display for FileProcessorError {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        match self {
            FileProcessorError::FileNotFound(path) => {
                write!(f, "File not found: {}", path)
            }
            FileProcessorError::PermissionDenied(path) => {
                write!(f, "Permission denied: {}", path)
            }
            FileProcessorError::InvalidFormat(msg) => {
                write!(f, "Invalid format: {}", msg)
            }
            FileProcessorError::IoError(err) => {
                write!(f, "IO error: {}", err)
            }
        }
    }
}

impl std::error::Error for FileProcessorError {}

impl From<io::Error> for FileProcessorError {
    fn from(err: io::Error) -> Self {
        match err.kind() {
            io::ErrorKind::NotFound => {
                FileProcessorError::FileNotFound("Unknown file".to_string())
            }
            io::ErrorKind::PermissionDenied => {
                FileProcessorError::PermissionDenied("Unknown file".to_string())
            }
            _ => FileProcessorError::IoError(err),
        }
    }
}

struct FileProcessor;

impl FileProcessor {
    fn read_and_count_lines(path: &str) -> Result<usize, FileProcessorError> {
        if !Path::new(path).exists() {
            return Err(FileProcessorError::FileNotFound(path.to_string()));
        }
        
        let content = fs::read_to_string(path)?;
        Ok(content.lines().count())
    }
    
    fn copy_file(src: &str, dst: &str) -> Result<(), FileProcessorError> {
        if !Path::new(src).exists() {
            return Err(FileProcessorError::FileNotFound(src.to_string()));
        }
        
        fs::copy(src, dst)?;
        Ok(())
    }
    
    fn validate_json_file(path: &str) -> Result<(), FileProcessorError> {
        let content = fs::read_to_string(path)?;
        
        // 简单的JSON验证(实际项目中应该使用JSON库)
        if !content.trim_start().starts_with('{') || !content.trim_end().ends_with('}') {
            return Err(FileProcessorError::InvalidFormat(
                "File does not appear to be valid JSON".to_string()
            ));
        }
        
        Ok(())
    }
}

fn main() {
    // 测试行数统计
    match FileProcessor::read_and_count_lines("Cargo.toml") {
        Ok(lines) => println!("File has {} lines", lines),
        Err(error) => println!("Error reading file: {}", error),
    }
    
    // 测试文件复制
    match FileProcessor::copy_file("Cargo.toml", "Cargo_backup.toml") {
        Ok(()) => println!("File copied successfully"),
        Err(error) => println!("Error copying file: {}", error),
    }
    
    // 测试JSON验证
    match FileProcessor::validate_json_file("nonexistent.json") {
        Ok(()) => println!("JSON is valid"),
        Err(error) => println!("JSON validation error: {}", error),
    }
}
# Python文件处理器
import os
import shutil
import json
from typing import Optional

class FileProcessorError(Exception):
    """文件处理器基础异常"""
    pass

class FileNotFoundError(FileProcessorError):
    def __init__(self, path):
        super().__init__(f"File not found: {path}")

class PermissionDeniedError(FileProcessorError):
    def __init__(self, path):
        super().__init__(f"Permission denied: {path}")

class InvalidFormatError(FileProcessorError):
    def __init__(self, message):
        super().__init__(f"Invalid format: {message}")

class FileProcessor:
    @staticmethod
    def read_and_count_lines(path: str) -> int:
        if not os.path.exists(path):
            raise FileNotFoundError(path)
        
        try:
            with open(path, 'r', encoding='utf-8') as f:
                return sum(1 for _ in f)
        except PermissionError:
            raise PermissionDeniedError(path)
        except IOError as e:
            raise FileProcessorError(f"IO error: {e}")
    
    @staticmethod
    def copy_file(src: str, dst: str) -> None:
        if not os.path.exists(src):
            raise FileNotFoundError(src)
        
        try:
            shutil.copy2(src, dst)
        except PermissionError:
            raise PermissionDeniedError(src)
        except IOError as e:
            raise FileProcessorError(f"IO error: {e}")
    
    @staticmethod
    def validate_json_file(path: str) -> None:
        if not os.path.exists(path):
            raise FileNotFoundError(path)
        
        try:
            with open(path, 'r', encoding='utf-8') as f:
                json.load(f)
        except json.JSONDecodeError as e:
            raise InvalidFormatError(f"Invalid JSON: {e}")
        except PermissionError:
            raise PermissionDeniedError(path)
        except IOError as e:
            raise FileProcessorError(f"IO error: {e}")

def main():
    # 测试行数统计
    try:
        lines = FileProcessor.read_and_count_lines("requirements.txt")
        print(f"File has {lines} lines")
    except FileProcessorError as error:
        print(f"Error reading file: {error}")
    
    # 测试文件复制
    try:
        FileProcessor.copy_file("requirements.txt", "requirements_backup.txt")
        print("File copied successfully")
    except FileProcessorError as error:
        print(f"Error copying file: {error}")
    
    # 测试JSON验证
    try:
        FileProcessor.validate_json_file("nonexistent.json")
        print("JSON is valid")
    except FileProcessorError as error:
        print(f"JSON validation error: {error}")

if __name__ == "__main__":
    main()

6.8 本章小结

通过本章学习,你应该掌握:

  1. 错误分类:可恢复错误(Result)vs 不可恢复错误(panic!)
  2. Result类型:安全地处理可能失败的操作
  3. 错误传播:使用?操作符简化错误处理
  4. 自定义错误:创建特定领域的错误类型
  5. 错误转换:在不同错误类型间转换

与Python的关键差异:

特性RustPython
错误处理Result类型,编译时检查异常机制,运行时处理
错误传播?操作符,显式传播自动栈展开
错误分类可恢复/不可恢复统一异常模型
性能零成本抽象异常有运行时开销
强制处理编译器强制处理Result可以忽略异常

关键要点:

  • Rust强制你处理所有可能的错误情况
  • Result类型让错误处理成为类型系统的一部分
  • ?操作符提供了简洁的错误传播方式
  • 自定义错误类型提供更好的错误信息

下一章预告: 我们将学习Rust的特征系统和泛型,这是Rust实现多态的关键机制。