Generators
Generators and Iterators
Python
- Generators: Use
yield
for lazy evaluation.
- Iterators: Objects that implement
__iter__
and __next__
.
| def count_up_to(max):
count = 1
while count <= max:
yield count
count += 1
gen = count_up_to(5)
for i in gen:
print(i)
|
Rust
- Iterators: Core part of Rust, implemented via the
Iterator
trait.
- No direct equivalent to
yield
: But can achieve similar functionality with iterator adaptors or by implementing Iterator
trait.
| struct CountUpTo {
count: u32,
max: u32,
}
impl Iterator for CountUpTo {
type Item = u32;
fn next(&mut self) -> Option<Self::Item> {
if self.count <= self.max {
let ret = self.count;
self.count += 1;
Some(ret)
} else {
None
}
}
}
let counter = CountUpTo { count: 1, max: 5 };
for i in counter {
println!("{}", i);
}
|
Context Managers
Python
- Context Managers: Use
with
statement to automatically manage resources.
| with open('file.txt', 'r') as f:
file_contents = f.read()
|
Rust
- RAII (Resource Acquisition Is Initialization): Resources are released when the variable goes out of scope, similar to context managers. Uses the
Drop
trait.
| {
let f = File::open("file.txt").expect("Unable to open file");
// Use file
} // `f` goes out of scope and is automatically closed here
|
Asynchronous Programming
Python
- Async/Await: Python 3.5+ supports
async
and await
for asynchronous programming.
| import asyncio
async def fetch_data():
await asyncio.sleep(2)
return {'data': 1}
async def main():
result = await fetch_data()
print(result)
asyncio.run(main())
|
Rust
- Async/Await: Rust also supports
async
and await
, often used with tokio
or async-std
.
| use tokio;
#[tokio::main]
async fn main() {
let data = fetch_data().await;
println!("{:?}", data);
}
async fn fetch_data() -> Result<u32, &'static str> {
// Simulate an async operation
tokio::time::sleep(tokio::time::Duration::from_secs(2)).await;
Ok(1)
}
|
Concurrency
Python
- Threading and Multiprocessing: Due to GIL, multiprocessing is often used for CPU-bound tasks.
| from multiprocessing import Process
def process_data(data):
# Process data
pass
if __name__ == "__main__":
p = Process(target=process_data, args=(data,))
p.start()
p.join()
|
Rust
- Concurrency: Rust's ownership and type system allow for safe concurrency without a GIL. Uses
std::thread
, tokio
for async operations.
| use std::thread;
fn process_data(data: &str) {
// Process data
}
fn main() {
let data = "data";
let handle = thread::spawn(move || {
process_data(data);
});
handle.join().unwrap();
}
|
Continuing with advanced examples, each section showcases the unique aspects and best practices of Python and Rust in handling complex programming scenarios.