A guided path for Python developers who want to think in Rust.
Learn ownership, enums, and compiler-guided design.
This track is built for experienced Python developers moving into Rust. It focuses on the conceptual shifts that feel hardest at first: ownership, explicit state modeling, compiler-guided design, and the disciplined patterns that make Rust code trustworthy.
before you start
- $You already write real Python code. This path assumes professional instincts, not beginner-level programming lessons.
- $Expect comparison-first modules: each stop starts from familiar Python habits, then shows where Rust agrees or pushes back.
- $Plan to practice the target ecosystem directly — syntax, testing, and design choices should feel native by the end, not translated.
by the end you can
- →Read and write idiomatic Rust without translating every line back through Python.
- →Spot which Python instincts transfer cleanly and which ones need a different Rust mental model.
- →Use the six modules as a working checklist when you build your first real Rust tool, service, or feature.
syllabus
6 modules, one capstone.
Mindset shift
Move from Python's runtime flexibility to Rust's correctness-first feedback cycle.
Ownership and borrowing
Understand how Rust controls who owns data, who can borrow it, and when mutation is allowed.
Enums and pattern matching
Model variant-rich data directly with enums and handle it exhaustively with match expressions.
Option, Result, and errors
Translate Python's None and exception habits into Rust's explicit sum types and propagation patterns.
Traits and generics
Learn how Rust models shared behavior and reusable logic through traits and generics instead of class inheritance or pure duck typing.
Testing in Rust
Translate pytest habits into Rust's built-in test model, assertion macros, and common organization patterns.
track reference
Keep the shared translation aids in one place.
These are track-wide lookup tables and task patterns, not lesson-specific reading. Use them when you need a quick reset on the recurring source-to-target language translations.
Data type mappings
Recheck the building blocks when a translation starts to wobble.
Python
string
Rust
String or &str
Common operations
- Format values with f-strings in Python and format!/println! in Rust.
- Use owned String when data must be kept and &str when borrowing is enough.
- Treat ownership and borrowing as part of the string API decision.
Python
list
Rust
Vec<T>
Common operations
- Append with list.append(...) in Python and push(...) in Rust.
- Transform with comprehensions in Python and iterator chains or loops in Rust.
- Keep element type explicit in Rust instead of relying on mixed runtime shapes.
Python
dict
Rust
HashMap<K, V> or struct
Common operations
- Use HashMap when keyed lookup is dynamic and structs/enums when the shape is known.
- Prefer named structs when the shape is stable and part of the contract.
- Keep the data model explicit instead of leaving Python dict shape informal.
Python
None / missing value
Rust
Option<T> / Result<T, E>
Common operations
- Model ordinary absence with Option and failure with Result instead of collapsing them together.
- Let match or combinators keep missing-data handling explicit.
- Use the type system to separate not found from operation failed.
Comparative cheat sheet
Keep the most common tasks visible while you practice.
| Task | Python | Rust |
|---|---|---|
| Define a function | def greet(name: str) -> str:
return f"hello {name}" | fn greet(name: &str) -> String {
format!("hello {}", name)
} |
| Format a string | message = f"user={user_id}" | let message = format!("user={}", user_id); |
| Add to a collection | items.append(value) | items.push(value); |
| Handle missing data | if user is None:
return None | if user.is_none() {
return None;
} |
| Test a function | def test_slugify():
assert slugify("Hello") == "hello" | #[test]
fn slugify_works() {
assert_eq!(slugify("Hello"), "hello");
} |
capstone
Ship a small Rust project that proves the mental model stuck.
Build one focused artifact in Rust using the same comparison-first habits from the track: start from a familiar Python shape, then deliberately redesign it the way Rust expects.
- ●Translate a familiar Python data flow into idiomatic Rust structure instead of preserving the old shape by force.
- ●Apply the early modules to data modeling, control flow, and API boundaries before you add tooling, polish, or deployment concerns.
- ●Use the later modules to verify, test, and package the result the way Rust developers expect to see it shipped.
ready?
Start with module 01 — Mindset shift.