我在写了六年 Python 之后开始学 Rust。最初被 borrow checker 折磨得怀疑人生,但一旦理解其设计哲学,就会发现 Rust 和 Python 在「理念层」的对应关系比想象中更多。这篇文章写给那些想把 Rust 作为第二语言的 Python 开发者。

所有权 vs Python 引用计数

Python 的内存管理靠引用计数 + GC。你创建一个对象,Python 记录有多少个变量指向它,当计数归零时自动释放。Rust 则完全不一样:每个值有且只有一个所有者。当所有者离开作用域,值就被自动释放——不需要 GC,也不需要手动 free。

// Rust:所有权转移
let s1 = String::from("hello");
let s2 = s1;           // s1 的所有权转移给 s2
// println!("{}", s1); // 编译错误!s1 已经失效

# Python:引用计数
s1 = "hello"
s2 = s1                # s1 和 s2 都指向同一个对象
print(s1)              # 正常工作

Rust 的这一设计看似严苛,但消除了 Python 中常见的两类问题:数据竞争(多线程同时修改)和 use-after-free。编译器在编译期就帮你检查了所有内存安全问题。

Cargo vs pip:依赖管理的范式差异

Python 的包管理经历了 pip → pipenv → poetry → uv 的多次迭代仍然不够统一。而 Rust 的 Cargo 从一开始就是「一站式」工具:构建、测试、文档生成、依赖管理、发布全部集成在一起。一个 Cargo.toml 文件对应 Python 的 requirements.txt + setup.py + pyproject.toml 的全部功能,而且提供确定性的依赖锁定(Cargo.lock)。

# Cargo.toml
[package]
name = "my_project"
version = "0.1.0"

[dependencies]
serde = { version = "1.0", features = ["derive"] }
tokio = { version = "1", features = ["full"] }

Result vs Exception:错误处理的哲学分歧

Python 用 try/except 处理异常——异常可以跨越多层调用栈传播,你甚至不知道一个函数可能抛出什么异常。Rust 用 Result<T, E> 类型将错误编码进函数签名中:

// Rust:错误是返回值的一部分,编译器强制你处理
fn read_config(path: &str) -> Result<Config, io::Error> {
    let content = std::fs::read_to_string(path)?; // ? 是语法糖:出错就提前返回
    Ok(serde_json::from_str(&content)?)
}

? 操作符是 Rust 里我最喜欢的设计——它在语义上等价于「如果出错就 return 这个错误」,但写法极其简洁。相比于 Python 中你不知道哪个调用会抛出异常,Rust 的 Result 让错误路径一目了然。

闭包与 Python lambda 的异同

Rust 的闭包在语法上与 Python lambda 非常相似,但类型系统区分了三种闭包 trait:Fn(不可变借用)、FnMut(可变借用)和 FnOnce(获取所有权)。这让编译器能在编译期精确推断闭包是否线程安全、是否可以多次调用。

// Rust 闭包
let multiply = |x, y| x * y;
let result: i32 = multiply(3, 4); // 类型推断:i32

# Python lambda
multiply = lambda x, y: x * y
result = multiply(3, 4)

为什么 Rust 适合写 Python 扩展

Python 的性能瓶颈通常在于 CPU 密集型计算。用 C 写扩展太容易出错,Cython 语法又不够现代。Rust 通过 PyO3 提供了几乎零成本的 Python 互操作:直接用 Rust 写函数,编译成 .so/.pyd,Python 侧 import 即可使用。更重要的是,Rust 的内存安全保证让扩展不会因野指针导致 Python 解释器崩溃——这是 C 扩展最常见的灾难性 bug。

总结

Rust 难学吗?是的,最初几周会很难——主要是 borrow checker 让你觉得自己「不会写代码」。但度过这个阶段后,你会发现 Rust 的很多设计(所有权、Result、Cargo)带来的确定性远远超过了学习成本。对 Python 开发者来说,Rust 最实际的应用场景就是写高性能扩展,而 PyO3 让这件事变得前所未有的安全。

※ 全文约 790 字