可以复制粘贴本文代码:
- 在https://play.rust-lang.org/ 运行 Python
- 在https://repl.it/languages/python3 中运行 Rust 示例
安装新的库/包
Python
$ pip install foo
Rust
$ cargo install foo
运行编译:
Python
$ python my_python_program.py
Rust
$ cargo run
在 Rust 中,有一个 --release 标志可以在编译时进行更多优化,但编译时间会更长。
$ cargo run --release
你好世界
Hello World
Python
if <strong>name</strong> == "<strong>main</strong>": print("Hello, World")
|
Rust
fn main() { println!("Hello, World"); }
|
类型和声明
创建新对象、基本原始类型值和数据结构。
Python
age = 80 name = 'daffy' weight = 62.3 loons = ['bugs', 'daffy', 'taz'] ages = { # Ages for 2017 'daffy': 80, 'bugs': 79, 'taz': 63, }
|
Rust
use std::collections::HashMap;
fn main() { let age = 80; let name = "daffy"; let weight = 62.3; let mut loons = vec!["bugs", "daffy", "taz"];
let mut ages = HashMap::new(); // Ages for 2017 ages.insert("daffy", 80); ages.insert("bugs", 79); ages.insert("taz", 63); }
|
定义一个函数
定义一个接收 2 个整数参数并返回其和的函数。
Python
def add(a, b): """Adds a to b""" return a + b
|
带有类型注释的 Python
它看起来更类似于 Rust。
def add(a: int, b: int) -> int: """Adds a to b""" return a + b
|
Rust
/// Adds a to b fn add(a: i32, b: i32) -> i32 { a + b }
|
列表/切片
创建列表、添加新元素、获取列表长度、按索引分片、使用 for 循环迭代以及使用枚举器迭代。
Python
names = ['bugs', 'taz', 'tweety'] print(names[0]) # bugs names.append('elmer') print(len(names)) # 4 print(names[2:]) # ['tweety', 'elmer']
for name in names: print(name)
for i, name in enumerate(names): print('{} at {}'.format(name, i))
|
Rust
fn main() { let mut names = vec!["bugs", "taz", "tweety"]; println!("{}", names[0]); // bugs names.push("elmer"); println!("{}", names.len()); // 4 println!("{:?}", &names[2..]); // ["tweety", "elmer"]
for name in &names { println!("{}", name); }
for (i, name) in names.iter().enumerate() { println!("{} at {}", i, name); } }
|
.step_by() 相当于 python 的 range/xrange 步长参数。
python:
for i in range(0,10,2): print(i) # 0, 2, 4, 6, 8
|
rust:
for i in (0..10).step_by(2) { println!("{}", i); // 0, 2, 4, 6, 8 }
|
字典/地图
创建新字典(哈希映射)、添加新键和值、更改值、通过键获取、检查键是否包含等。
Python
#创建新二进制文件并填充 ages = {} ages['daffy'] = 80 ages['bugs'] = 79 ages['taz'] = 63
# 或使用 for 循环进行同样的操作 ages = {} for name, age in [("daffy", 80), ("bugs", 79), ("taz", 63)]: ages[name] = age
# or initializing from a list ages = dict([("daffy", 80), ("bugs", 79), ("taz", 63)])
#或在创建时传递键值 ages = { # Ages for 2017 'daffy': 80, 'bugs': 79, 'taz': 63, }
ages['elmer'] = 80 print(ages['bugs']) # 79 print('bugs' in ages) # True
del ages['taz']
for name in ages: # Keys print(name)
for name, age in ages.items(): # Keys & values print('{} is {} years old'.format(name, age))
|
Rust代码
use std::iter::FromIterator; use std::collections::HashMap;
fn main() {
// 创建新的 HashMap 并填充它 let mut ages = HashMap::new(); // Ages for 2017 ages.insert("daffy", 80); ages.insert("bugs", 79); ages.insert("taz", 63);
// 或使用循环进行同样的操作 let mut ages = HashMap::new(); for &(name, age) in [("daffy", 80), ("bugs", 79), ("taz", 63)].iter() { // For non-Copy data, remove & and use iter().clone() ages.insert(name, age); }
// 或从数组初始化 let mut ages: HashMap<&str, i32> = // Ages for 2017 [("daffy", 80), ("bugs", 79), ("taz", 63)] .iter().cloned().collect();
// 或从 Vec(迭代器)初始化 let mut ages: HashMap<&str, i32> = // Ages for 2017 HashMap::from_iter( vec![ ("daffy", 80), ("bugs", 79), ("taz", 63) ] );
ages.insert("elmer", 80); println!("{}", ages["bugs"]); // 79 println!("{}", ages.contains_key("bugs")); // true ages.remove("taz");
for name in ages.keys() { // Keys println!("{}", name); }
for (name, age) in &ages { // Keys & values println!("{} is {} years old", name, age); }
}
|
在 Rust 中用 Pythonic 替代 dict/map
你可以使用 maplit crate 来加载 hashmap! 宏,以获得高效的糖化(又称 Pythonic)语法!
# Cargo.toml [dependencies] maplit = "*"
|
#[macro_use] extern crate maplit;
let map = hashmap!{ "daffy" => 80, "bugs" => 79, "taz" => 63, };
|
集合/哈希集
创建集合(由唯一键组成的哈希值),添加新键并计算交集、差集和合集
Python
# 创建和填充 colors = set() colors.add("red") colors.add("green") colors.add("blue") colors.add("blue")
# using literal syntax colors = {'red', 'green', 'blue', 'blue'}
# from an iterator colors = set(['red', 'green', 'blue', 'blue'])
# deduplication print(colors) # {"blue", "green", "red"}
# operations colors = {'red', 'green', 'blue', 'blue'} flag_colors = {"red", "black"}
# difference colors.difference(flag_colors) # {'blue', 'green'}
# 对称差 colors.symmetric_difference(flag_colors) # {'black', 'blue', 'green'}
# 交叉点intersection colors.intersection(flag_colors) # {'red'}
# union colors.union(flag_colors) # {'black', 'blue', 'green', 'red'}
Rust use std::collections::HashSet; use std::iter::FromIterator;
fn main() {
// 创建和填充 - 类型推断 let mut colors = HashSet::new(); colors.insert("red"); colors.insert("green"); colors.insert("blue"); colors.insert("blue");
// from an iterator -显式类型 let mut colors: HashSet<&str> = HashSet::from_iter(vec!["red", "green", "blue", "blue"]);
// 重复数据删除deduplication println!("{:?}", colors); // {"blue", "green", "red"}
// Operations let mut colors: HashSet<&str> = HashSet::from_iter(vec!["red", "green", "blue", "blue"]); let mut flag_colors: HashSet<&str> = HashSet::from_iter(vec!["red", "black"]);
// difference colors.difference(&flag_colors); // ["green", "blue"]
// 对称差symmetric difference colors.symmetric_difference(&flag_colors); // ["blue", "green", "black"]
// intersection colors.intersection(&flag_colors); // ["red"]
// union colors.union(&flag_colors); // ["red", "blue", "green", "black"] }
|
或使用 maplit crate 进行语法润色
#[macro_use] extern crate maplit;
let colors = hashset!{"red", "green", "blue", "blue"};
|
While 和 For 循环
循环,直到满足某个条件或遍历一个可迭代对象。
Python
# While loop
counter = 0 while counter < 10: print(counter) counter += 1
# infinite while loop while True: print("loop Forever!")
# infinite while loop with break counter = 0 while True: print(counter) counter += 1 if counter >= 10: break
# while loop with continue counter = 0 while True: counter += 1 if counter == 5: continue print(counter) if counter >= 10: break
# For loop over a list for color in ["red", "green", "blue"]: print(color)
# Enumerating indexes for i, color in enumerate(["red", "green", "blue"]): print(f"{color} at index {i}")
# For in a range for number in range(0, 100): print(number) # from 0 to 99
|
Rust
fn main() {
// While loop let mut counter = 0; while counter < 10 { println!("{}", counter); counter += 1; }
// infinite while loop loop { println!("Loop forever!"); }
// infinite while loop with break let mut counter = 0; loop { println!("{}", counter); counter += 1; if counter >= 10 { break; } }
// infinite while loop with continue let mut counter = 0; loop { counter += 1; if counter == 5 { continue; } println!("{}", counter); if counter >= 10 { break; } }
// for loop over a list for color in ["red", "green", "blue"].iter() { println!("{}", color); }
// Enumerating indexes for (i, color) in ["red", "green", "blue"].iter().enumerate() { println!("{} at index {}", color, i); }
// for in a range for number in 0..100 { println!("{}", number); // from 0 to 99 } }
|
Rust 具有 Python 所没有的循环功能:Loop Labels循环标签
'outer: for x in 0..10 { 'inner: for y in 0..10 { if x % 2 == 0 { continue 'outer; } // continues the loop over x if y % 2 == 0 { continue 'inner; } // continues the loop over y println!("x: {}, y: {}", x, y); } }
|
文件
读取文本文件并逐行打印内容,最后正确关闭文件。
Python
from pathlib import Path
with Path("/tmp/song.txt").open() as fp: # Iterate over lines for line in fp: print(line.strip())
|
Rust
use std::io::{BufReader, BufRead}; use std::fs::File; use std::path::Path;
fn main () { let fp = File::open(Path::new("/tmp/song.txt")).unwrap(); let file = BufReader::new(&fp); for line in file.lines() { // Iterate over lines println!("{}", line.unwrap()); } }
|
异常/返回错误
期望出现异常并识别错误。
Python
def div(a, b): if b == 0: raise ValueError("b can't be 0") return a / b
# ...
try: div(1, 0) except ValueError: print('An error occurred!')
|
Rust
fn div(a: i32, b: i32) -> Result<i32, &'static str> { if b == 0 { Err("b can't be 0") } else { Ok(a / b) } }
fn main() { match div(1, 0) { Ok(_) => {}, Err(_) => println!("An error occurred!"), }; }
|
并发性
Python
thr = Thread(target=add, args=(1, 2), daemon=True) thr.start()
|
Rust
use std::thread;
[code]thread::spawn(|| { add(5,5); });
|
[/code]
线程间通信
管理线程之间的数据上下文。
Python
from queue import Queue queue = Queue() # ... # Send message from a thread queue.put(353)
# ... # Get message to a thread val = queue.get()
|
Rust
use std::thread; use std::sync::mpsc;
fn main() { let (tx, rx) = mpsc::channel();
let sender = thread::spawn(move || { let val = String::from("hi"); tx.send(val.clone()).unwrap(); println!("Sent {}", val); });
let receiver = thread::spawn(move || { let received = rx.recv().unwrap(); println!("Received: {}", received); });
sender.join(); receiver.join(); }
|
排序
对列表进行排序、反转和使用按键。
Python
names = ['taz', 'bugs', 'daffy']
# Lexicographical order names.sort()
# Reversed lexicographical order names.sort(reverse=True)
# Sort by length names.sort(key=len)
|
Rust
fn main() { let mut names = ["taz", "bugs", "daffy"];
// Lexicographical order names.sort();
// Reversed lexicographical order names.sort_by(|a, b| b.cmp(a));
// Sort by length names.sort_by_key(|a| a.len()); }
|
带有 Flask / Rocket 的 Web 应用程序
Python
from flask import Flask
app = Flask(<strong>name</strong>)
@app.route('/') def index(): return 'Hello Python'
if <strong>name</strong> == '<strong>main</strong>': app.run(port=8080)
|
Rust
#![feature(plugin)] #![plugin(rocket_codegen)]
extern crate rocket;
#[get("/")] fn index() -> &'static str { "Hello Rust" }
fn main() { rocket::ignite().mount("/", routes![index]).launch(); }
|
具有错误处理功能的 HTTP 请求
Python使用 requests
import requests
url = 'https://httpbin.org/ip'
try: resp = requests.get(url) except HTTPError as err: msg = f"error: cannot get {url} - {err}" raise SystemExit(msg)
assert resp.status_code == 200
print(f"The response content is: {resp.content}")
|
Rust使用reqwest
extern crate reqwest; use std::io::Read;
fn main() { let url = "https://httpbin.org/ip";
let mut resp = match reqwest::get(url) { Ok(response) => response, Err(e) => panic!("error: could not perform get request {}", e), };
assert!(resp.status().is_success());
let mut content = String::new(); resp.read_to_string(&mut content).expect("valid UTF-8");
println!("The response content is: {}", content); }
|
多线程HTTP爬虫
使用requests
from concurrent.futures import ThreadPoolExecutor import requests
URLS = ( "https://httpbin.org/html", "https://httpbin.org/links/10/0", "https://httpbin.org/robots.txt", "https://httpbin.org/user-agent", "https://httpbin.org/links/10/0", "https://httpbin.org/robots.txt", "https://httpbin.org/xml", "https://httpbin.org/redirect/1", "https://httpbin.org/redirect/2", "https://httpbin.org/cookies", "https://httpbin.org/basic-auth/user/passwd", "https://httpbin.org/gzip", )
def crawl_worker(url): try: print(f"Response of url: {url} is {requests.get(url).status_code}") except Exception: print("Failed to get url.")
if <strong>name</strong> == "<strong>main</strong>": with ThreadPoolExecutor() as executor: executor.map(crawl_worker, URLS)
|
Rust使用reqwest
extern crate reqwest; use std::thread;
fn crawl_worker(url: &str) { let parsed_url = reqwest::Url::parse(url).expect("Bad url format."); let response = reqwest::get(parsed_url).expect("Failed to get url."); println!("Response of url: {} is {:?}", url, response.status().to_string()); }
fn main() { let urls = vec![ "https://httpbin.org/html", "https://httpbin.org/links/10/0", "https://httpbin.org/robots.txt", "https://httpbin.org/user-agent", "https://httpbin.org/links/10/0", "https://httpbin.org/robots.txt", "https://httpbin.org/xml", "https://httpbin.org/redirect/1", "https://httpbin.org/redirect/2", "https://httpbin.org/cookies", "https://httpbin.org/basic-auth/user/passwd", "https://httpbin.org/gzip", ]; let mut queue = vec![];
for url in urls { queue.push(thread::spawn(move || { crawl_worker(url); })); }
for job in queue { let _ = job.join(); } }
|
JSON 编码和解码
Python
import json
# Decode/Deserialize data = '''{ "name": "bugs", "age": 76 }'''
person = json.loads(data)
# 与其他 Python 数据结构一样进行操作 print(f"{person['name']} was born {person['age']} years ago")
# Encode/Serialize serialized = json.dumps(obj) print(f"The serialized value is: {serialized}")
|
Rust
extern crate serde; extern crate serde_json;
#[macro_use] extern crate serde_derive;
#[derive(Serialize, Deserialize)] struct Person { name: String, age: u8, }
fn main() { // Decode/Deserialize let data = r#"{"name": "bugs", "age": 76}"#;
let p: Person = match serde_json::from_str(data) { Ok(person) => person, Err(e) => panic!("error: could not deserialize: {}", e), };
// 就像使用其他 Rust 数据结构一样。 println!("{} was born {} years ago.", p.name, p.age);
// Encode/Serialize let serialized = serde_json::to_string(&p).unwrap(); println!("The serialized value is: {}", serialized); }
|
面向对象
Python:
class Cat: def <strong>init</strong>(self, name): self.name = name
def greet(self, other): print("Meow {}, I'm {}".format(other, self.name))
# ...
grumy = Cat('Grumpy') grumy.greet('Garfield') # Meow Garfield, I'm Grumpy
|
Rust
struct Cat { name: String }
impl Cat {
pub fn new<S>(name: S) -> Cat where S: Into<String> { Cat { name: name.into() } } pub fn greet<S: Into<String>>(&self, other:S) { println!("Meow {}, I'm {}", other.into(), self.name); } }
fn main() { let grumpy = Cat::new("Grumpy"); grumpy.greet("Garfield"); // Meow Garfield, I'm Grumpy }
|
注意:在 Rust 中,最好避免使用字符串类型的 API,因此在上面的示例中,我们最好让 garfield = Cat::new("Garfield") 并接受 Cat 的实例作为其他参数。
打印调试/日志对象
打印格式化对象调试信息
Python
class Actor: def <strong>init</strong>(self, name, age): self.name = name self.age = age
def <strong>repr</strong>(self): return str(self.<strong>dict</strong>)
daffy = Actor( name='Daffy', age=80, )
print('{!r}'.format(daffy)) # {'name': 'Daffy', 'age': 80}
|
Rust
#[derive(Debug)] struct Actor { name: String, age: i32 }
fn main() { let daffy = Actor {name: "Daffy".into(), age: 80}; println!("{:#?}", daffy); // Actor {name: "Daffy", age: 80 } }
|