6 minutes
Rust pour développeurs Python
Petit guide rapide pour les Pythonistas
souhaitant devenir Rustaceans
.
Python
1. Conventions et guidelines
PEP8
PEP8
2. Tooling
- requirements.txt
- setup.py
- PyPI
- pip
- setuptools & poetry pour distribuer des libs
- pipenv pour la gestion des dépendances
- twine pour uploader un package
- venv pour isoler un env
- pyenv pour gérer ≠ versions de Python
- pydoc & Sphinx pour générer la doc
- Python pour interpréter/ compiler
- ipython comme REPL
- ipdb pour debugguer
3. Librairies et frameworks
4. Python like features
- dict
- constructor avec valeurs par défaut
- itertools
- hashlib
5. Hello world
if __name__ == "__main__":
print("Hello, World")
6. Types
age = 33
name = 'olivier'
weight = 75.3
cartoons = ['riri', 'fifi', 'loulou']
ages = {
'riri': 7,
'fifi': 7,
'loulou': 7,
}
7. Fonctions
def substract(a: int, b: int) -> int:
"""Substracts b from a"""
return a - b
8. Manipulation de listes
cartoons = ["riri", "fifi", "loulou"]
print(cartoons[0]) # riri
cartoons.append("donald")
print(len(cartoons)) # 4
print(cartoons[2:]) # ["loulou", "donald"]
for cartoon in cartoons:
print(cartoon)
for i, cartoon in enumerate(cartoons):
print(f"{cartoon} at {i}")
# Lexicographical order
cartoons.sort()
# Reversed lexicographical order
cartoons.sort(reverse=True)
# Sort by length
cartoons.gpg(key=len)
9. Range
for i in range(0,6,2):
print(i) # 0, 2, 4
10. Manipulation de dictionnaires (hash map)
# Create new dict
cartoons_age = {}
cartoons_age["riri"] = 7
cartoons_age["fifi"] = 7
cartoons_age["loulou"] = 7
# or using for loop
cartoons_age = {}
for cartoon, age in [("riri", 7), ("fifi", 7), ("loulou", 7)]:
cartoons_age[cartoon] = age
# or using a list
cartoons_age = dict([("riri", 7), ("fifi", 7), ("loulou", 7)])
# or using key values
cartoons_age = {
"riri": 7,
"fifi": 7,
"loulou": 7,
}
cartoons_age["donald"] = 45
print(cartoons_age["riri"]) # 7
print("riri" in cartoons_age) # True
del cartoons_age["loulou"]
for cartoon in cartoons_age: # Keys
print(cartoon)
for cartoon, age in cartoons_age.items(): # Keys & values
print(f"{cartoon} is {age} years old")
11. Lire contenu d'un fichier
from pathlib import Path
with Path("/tmp/mon_fichier.txt").open() as fp:
# Iterate over lines
for line in fp:
print(line.strip())
12. Exceptions/ Retour d'erreur
def div(a, b):
if b == 0:
raise ValueError("Division par 0 impossible")
return a / b
try:
div(1, 0)
except ValueError:
print('Oops an error occurred!')
13. "Printer" des objets
class Cartoon:
def __init__(self, name, age):
self.name = name
self.age = age
def __repr__(self):
return str(self.__dict__)
riri = Cartoon(
name='Riri',
age=7,
)
print('{!r}'.format(riri))
# {'name': 'Riri', 'age': 7}
14. Set (hashSet)
cartoons = set()
cartoons.add("riri")
cartoons.add("fifi")
cartoons.add("loulou")
cartoons.add("loulou")
# or using literal syntax
cartoons = {'riri', 'fifi', 'loulou', 'loulou'}
# or using an iterator
cartoons = set(['riri', 'fifi', 'loulou', 'loulou'])
# Manipulation sur les sets
cartoons = {'riri', 'fifi', 'loulou', 'donald', 'picsou'}
some_cartoons = {"donald", "picsou"}
# difference
print(cartoons.difference(some_cartoons))
# {'riri', 'fifi', 'loulou'}
# intersection
print(cartoons.intersection(some_cartoons))
# {'donald', picsou}
# union
print(cartoons.union(some_cartoons))
# {'riri', 'fifi', 'loulou', 'donald', 'picsou'}
15. while et for loops
# While loop
counter = 0
while counter < 10:
print(counter)
counter += 1
# infinite while loop
while True:
print("Infinite loop")
# 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 cartoon in ["riri", "fifi", "loulou"]:
print(cartoon)
# Enumerating indexes
for i, cartoon in enumerate(["riri", "fifi", "loulou"]):
print(f"{cartoon} at index {i}")
# For in a range
for number in range(0, 100):
print(number) # from 0 to 99
16. Flask vs Rocket
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return 'Hello Python'
if __name__ == '__main__':
app.run(port=8080)
17. Request vs Reqwest
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}")
18. JSON encoding decoding
import json
# Decode/Deserialize
cartoon_data = '''{
"name": "riri",
"age": 7
}'''
cartoon = json.loads(cartoon_data)
# Do things like with any other Python data structure
print(f"{cartoon['name']} was born {cartoon['age']} years ago")
# Encode/Serialize
serialized = json.dumps(obj)
print(f"The serialized value is: {serialized}")
19. Object oriented
class Soldier:
def __init__(self, name: str):
self.name = name
def present(self, other_family_name: str):
print(f"Hi M. {other}, I'm solider {self.name}")
# ...
soldier = Soldier("Ryan")
soldier.present("Bond")
Rust
1. Conventions et guidelines
RustAPI Guidelines
RustAPI Guidelines
2. Tooling
3. Librairies et frameworks
4. Python like features
5. Hello world
fn main() {
println!("Hello, World");
}
6. Types
use std::collections::HashMap;
fn main() {
let age = 33;
let name = "olivier";
let weight = 75.3;
let mut cartoons = vec!["riri", "fifi", "loulou"];
let mut ages = HashMap::new();
ages.insert("riri", 7);
ages.insert("fifi", 7);
ages.insert("loulou", 7);
}
7. Fonctions
/// Substracts b from a
fn substract(a: i32, b: i32) -> i32 {
a - b
}
8. Manipulation de listes
fn main() {
let mut cartoons = vec!["riri", "fifi", "loulou"];
println!("{}", cartoons[0]); // riri
cartoons.push("donald");
println!("{}", cartoons.len()); // 4
println!("{:?}", &cartoons[2..]); // ["loulou", "donald"]
for cartoon in &cartoons {
println!("{}", cartoon);
}
for (i, cartoon) in cartoons.iter().enumerate() {
println!("{} at {}", i, cartoon);
}
// Lexicographical order
cartoons.sort();
// Reversed lexicographical order
cartoons.sort_by(|a, b| b.cmp(a));
// Sort by length
cartoons.sort_by_key(|a| a.len());
}
9. Range
for i in (0..6).step_by(2) {
println!("{}", i); // 0, 2, 4
}
10. Manipulation de dictionnaires (hash map)
Alternative
Ajouter la dependency dans Cargo.toml
Puis utiliser juste:
use std::iter::FromIterator;
use std::collections::HashMap;
fn main() {
// Create new HashMap
let mut cartoons_ages = HashMap::new();
cartoons_ages.insert("riri", 7);
cartoons_ages.insert("fifi", 7);
cartoons_ages.insert("loulou", 7);
// or using a loop
let mut cartoons_ages = HashMap::new();
for &(name, age) in [("riri", 7), ("fifi", 7), ("loulou", 7)].iter() {
// Possible to remove & and use iter().clone()
cartoons_ages.insert(name, age);
}
// or using an Array
let mut cartoons_ages: HashMap<&str, i32> =
[("riri", 7),
("fifi", 7),
("loulou", 7)]
.iter().cloned().collect();
// or using a Vec (Iterator)
let mut cartoons_ages: HashMap<&str, i32> =
HashMap::from_iter(
vec![
("riri", 7),
("fifi", 7),
("taz", 7)
]
);
cartoons_ages.insert("donald", 45);
println!("{}", cartoons_ages["fifi"]); // 7
println!("{}", cartoons_ages.contains_key("fifi")); // true
cartoons_ages.remove("loulou");
for name in cartoons_ages.keys() { // Keys
println!("{}", name);
}
for (name, age) in &cartoons_ages { // Keys & values
println!("{} is {} years old", name, age);
}
}
Alternative
Ajouter la dependency dans Cargo.toml
[dependencies]
maplit = "*"
Puis utiliser juste:
#[macro_use] extern crate maplit;
let map = hashmap!{
"riri" => 7,
"fifi" => 7,
"loulou" => 7,
};
11. Lire contenu d'un fichier
use std::io::{BufReader, BufRead};
use std::fs::File;
use std::path::Path;
fn main () {
let fp = File::open(Path::new("/tmp/mon_fichier.txt")).unwrap();
let file = BufReader::new(&fp);
for line in file.lines() {
// Iterate over lines
println!("{}", line.unwrap());
}
}
12. Exceptions/ Retour d'erreur
fn div(a: f64, b: f64) -> Result {
if b == 0 {
Err("Division par 0 impossible")
} else {
Ok(a / b)
}
}
fn main() {
match div(1, 0) {
Ok(_) => {},
Err(_) => println!("Oops an error occurred!"),
};
}
13. "Printer" des objets
#[derive(Debug)]
struct Cartoon {
name: String,
age: i32
}
fn main() {
let riri = Cartoon {name: "Riri".into(), age: 7};
println!("{:#?}", riri);
// Actor {name: "Riri", age: 7 }
}
14. Set (hashSet)
Alternative
Ajouter la dependency dans Cargo.toml
Puis utiliser juste:
use std::collections::HashSet;
use std::iter::FromIterator;
fn main() {
let mut cartoons = HashSet::new();
cartoons.insert("riri");
cartoons.insert("fifi");
cartoons.insert("loulou");
cartoons.insert("loulou");
// from an iterator
let mut cartoons: HashSet<&str> = HashSet::from_iter(vec!["riri", "fifi", "loulou", "loulou"]);
// deduplication
println!("{:?}", cartoons);
// {"riri", "fifi", "loulou"}
// Manipulation sur les hashSet
let mut cartoons: HashSet<&str> = HashSet::from_iter(vec!["riri", "fifi", "loulou", "loulou", "donald", "picsou"]);
let mut some_cartoons: HashSet<&str> = HashSet::from_iter(vec!["donald", "picsou"]);
// difference
cartoons.difference(&some_cartoons);
// ["riri", "fifi", "loulou"]
// intersection
cartoons.intersection(&some_cartoons);
// ["riri"]
// union
cartoons.union(&some_cartoons);
// ["red", "fifi", "loulou, "donald", "picsou"]
}
Alternative
Ajouter la dependency dans Cargo.toml
[dependencies]
maplit = "*"
Puis utiliser juste:
#[macro_use] extern crate maplit;
let cartoons = hashset!{"riri", "fifi", "loulou", "loulou"};
15. while et for loops
fn main() {
// While loop
let mut counter = 0;
while counter < 10 {
println!("{}", counter);
counter += 1;
}
// infinite while loop
loop {
println!("Infinite loop");
}
// 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 cartoon in ["riri", "fifi", "loulou"].iter() {
println!("{}", cartoon);
}
// Enumerating indexes
for (i, cartoon) in ["riri", "fifi", "loulou"].iter().enumerate() {
println!("{} at index {}", cartoon, i);
}
// for in a range
for number in 0..100 {
println!("{}", number);
// from 0 to 99
}
}
16. Flask vs Rocket
#![feature(plugin)]
#![plugin(rocket_codegen)]
extern crate rocket;
#[get("/")]
fn index() -> &'static str {
"Hello Rust"
}
fn main() {
rocket::ignite().mount("/", routes![index]).launch();
}
17. Request vs 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);
}
18. JSON encoding decoding
extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;
#[derive(Serialize, Deserialize)]
struct Cartoon {
name: String,
age: u8,
}
fn main() {
// Decode/Deserialize
let cartoon_data = r#"{"name": "riri", "age": 7}"#;
let c: Cartoon = match serde_json::from_str(cartoon_data) {
Ok(cartoon) => cartoon,
Err(e) => panic!("error: could not deserialize: {}", e),
};
// Do things just like with any other Rust data structure.
println!("{} was born {} years ago.", c.name, c.age);
// Encode/Serialize
let serialized = serde_json::to_string(&c).unwrap();
println!("The serialized value is: {}", serialized);
}
19. Object oriented
struct Soldier {
name: String
}
impl Soldier {
pub fn new<S>(name: S) -> Soldier where S: Into {
Soldier { name: name.into() }
}
pub fn present>(&self, other_family_name:S) {
println!("Hi M. {}, I'm {}", other_family_name.into(), self.name);
}
}
fn main() {
let soldier = Soldier::new("Ryan");
soldier.present("Bond");
}