控制流
您将学到: 不需要括号但需要花括号的
if/else、loop/while/forvs Python 的迭代模型、表达式块(一切都可以返回值)以及带强制返回类型的函数签名。难度: 初级
if/else
Section titled “if/else”# Pythonif temperature > 100: print("Too hot!")elif temperature < 0: print("Too cold!")else: print("Just right")
# 三元运算符status = "hot" if temperature > 100 else "ok"// Rust — 需要花括号,不需要冒号,`else if` 不是 `elif`if temperature > 100 { println!("Too hot!");} else if temperature < 0 { println!("Too cold!");} else { println!("Just right");}
// if 是表达式 — 返回值(类似 Python 三元运算符,但更强大)let status = if temperature > 100 { "hot" } else { "ok" };// 1. 条件必须是 bool — 没有真值/假值let x = 42;// if x { } // ❌ 错误:期望 bool,得到整数if x != 0 { } // ✅ 需要显式比较
// 在 Python 中,这些都是真值/假值:// if []: → False (空列表)// if "": → False (空字符串)// if 0: → False (零)// if None: → False
// 在 Rust 中,只有 bool 能在条件中使用:let items: Vec<i32> = vec![];// if items { } // ❌ 错误if !items.is_empty() { } // ✅ 显式检查
let name = "";// if name { } // ❌ 错误if !name.is_empty() { } // ✅ 显式检查for 循环
Section titled “for 循环”# Pythonfor i in range(5): print(i)
for item in ["a", "b", "c"]: print(item)
for i, item in enumerate(["a", "b", "c"]): print(f"{i}: {item}")
for key, value in {"x": 1, "y": 2}.items(): print(f"{key} = {value}")// Rustfor i in 0..5 { // range(5) → 0..5 println!("{}", i);}
for item in ["a", "b", "c"] { // 直接迭代 println!("{}", item);}
for (i, item) in ["a", "b", "c"].iter().enumerate() { // enumerate() println!("{}: {}", i, item);}
// HashMap 迭代use std::collections::HashMap;let map = HashMap::from([("x", 1), ("y", 2)]);for (key, value) in &map { // & 借用 map println!("{} = {}", key, value);}Python: Rust: 备注:range(5) 0..5 半开(不含结尾)range(1, 10) 1..10 半开range(1, 11) 1..=10 包含性(含结尾)range(0, 10, 2) (0..10).step_by(2) 步长(方法,不是语法)while 循环
Section titled “while 循环”# Pythoncount = 0while count < 5: print(count) count += 1
# 无限循环while True: data = get_input() if data == "quit": break// Rustlet mut count = 0;while count < 5 { println!("{}", count); count += 1;}
// 无限循环 — 使用 `loop`,不是 `while true`loop { let data = get_input(); if data == "quit" { break; }}
// loop 可以返回值!(Rust 独有)let result = loop { let input = get_input(); if let Ok(num) = input.parse::<i32>() { break num; // `break` 带值 — 类似循环的 return } println!("Not a number, try again");};列表推导式 vs 迭代器链
Section titled “列表推导式 vs 迭代器链”# Python — 列表推导式squares = [x ** 2 for x in range(10)]evens = [x for x in range(20) if x % 2 == 0]pairs = [(x, y) for x in range(3) for y in range(3)]// Rust — 迭代器链(.map、.filter、.collect)let squares: Vec<i32> = (0..10).map(|x| x * x).collect();let evens: Vec<i32> = (0..20).filter(|x| x % 2 == 0).collect();let pairs: Vec<(i32, i32)> = (0..3) .flat_map(|x| (0..3).map(move |y| (x, y))) .collect();
// 这些是惰性的 — 直到 .collect() 才会执行// Python 推导式是急切的(立即执行)// Rust 迭代器对大型数据集可以更高效Rust 中一切都是表达式(或可以是)。这是 Python 的重大转变,Python 中 if/for 是语句。
# Python — if 是语句(除了三元运算符)if condition: result = "yes"else: result = "no"
# 或者三元运算符(仅限于一个表达式):result = "yes" if condition else "no"// Rust — if 是表达式(返回值)let result = if condition { "yes" } else { "no" };
// 块是表达式 — 最后一行(没有分号)是返回值let value = { let x = 5; let y = 10; x + y // 没有分号 → 这是块的值(15)};
// match 也是表达式let description = match temperature { t if t > 100 => "boiling", t if t > 50 => "hot", t if t > 20 => "warm", _ => "cold",};下图说明了 Python 基于语句和 Rust 基于表达式的控制流之间的核心差异:
flowchart LR subgraph Python ["Python — 语句"] P1["if condition:"] --> P2["result = 'yes'"] P1 --> P3["result = 'no'"] P2 --> P4["result used later"] P3 --> P4 end subgraph Rust ["Rust — 表达式"] R1["let result = if cond"] --> R2["{ 'yes' }"] R1 --> R3["{ 'no' }"] R2 --> R4["value returned directly"] R3 --> R4 end style Python fill:#ffeeba style Rust fill:#d4edda分号规则:在 Rust 中,块中没有分号的最后表达式是块的返回值。加上分号使其成为语句(返回
())。 这让 Python 开发者初期感到困惑——它像是隐式的return。
函数与类型签名
Section titled “函数与类型签名”Python 函数
Section titled “Python 函数”# Python — 类型可选,动态分发def greet(name: str, greeting: str = "Hello") -> str: return f"{greeting}, {name}!"
# 默认参数、*args、**kwargsdef flexible(*args, **kwargs): pass
# 一等函数def apply(f, x): return f(x)
result = apply(lambda x: x * 2, 5) # 10Rust 函数
Section titled “Rust 函数”// Rust — 函数签名上类型必需,无默认值fn greet(name: &str, greeting: &str) -> String { format!("{}, {}!", greeting, name)}
// 无默认参数 — 使用 builder 模式或 Optionfn greet_with_default(name: &str, greeting: Option<&str>) -> String { let greeting = greeting.unwrap_or("Hello"); format!("{}, {}!", greeting, name)}
// 无 *args/**kwargs — 使用切片或结构体fn sum_all(numbers: &[i32]) -> i32 { numbers.iter().sum()}
// 一等函数和闭包fn apply(f: fn(i32) -> i32, x: i32) -> i32 { f(x)}
let result = apply(|x| x * 2, 5); // 10# Python — return 是显式的,None 是隐式的def divide(a, b): if b == 0: return None # 或抛出异常 return a / b// Rust — 最后一个表达式是返回值(无分号)fn divide(a: f64, b: f64) -> Option<f64> { if b == 0.0 { None // 提前返回(也可以写 `return None;`) } else { Some(a / b) // 最后的表达式 — 隐式返回 }}# Python — 返回元组def min_max(numbers): return min(numbers), max(numbers)
lo, hi = min_max([3, 1, 4, 1, 5])// Rust — 返回元组(相同概念!)fn min_max(numbers: &[i32]) -> (i32, i32) { let min = *numbers.iter().min().unwrap(); let max = *numbers.iter().max().unwrap(); (min, max)}
let (lo, hi) = min_max(&[3, 1, 4, 1, 5]);方法:self vs &self vs &mut self
Section titled “方法:self vs &self vs &mut self”// 在 Python 中,`self` 始终是可变引用。// 在 Rust 中,您选择:
impl MyStruct { fn new() -> Self { ... } // 无 self — "静态方法" / "classmethod" fn read_only(&self) { ... } // &self — 不可变借用(不能修改) fn modify(&mut self) { ... } // &mut self — 可变借用(可以修改) fn consume(self) { ... } // self — 获得所有权(对象被移动)}
// Python 等效:// class MyStruct:// @classmethod// def new(cls): ... # 不需要实例// def read_only(self): ... # Python 中三者相同:// def modify(self): ... # Python self 总是可变的// def consume(self): ... # Python 从不"消耗" self🏋️ 练习:使用表达式的 FizzBuzz(点击展开)
挑战:用 Rust 基于表达式的 match 写 1..=30 的 FizzBuzz。每个数字打印 “Fizz”、“Buzz”、“FizzBuzz” 或数字。使用 match (n % 3, n % 5) 作为表达式。
🔑 答案
fn main() { for n in 1..=30 { let result = match (n % 3, n % 5) { (0, 0) => String::from("FizzBuzz"), (0, _) => String::from("Fizz"), (_, 0) => String::from("Buzz"), _ => n.to_string(), }; println!("{result}"); }}关键收获:match 是返回值的表达式——不需要 if/elif/else 链。_ 通配符替换 Python 的 case _: 默认情况。