Apprendre Python de zéro jusqu'au niveau expert : syntaxe, structures de données, POO, générateurs, décorateurs, typage, tests, async et internals du langage.
Une fonction nomme un bloc de code réutilisable. En Python, c'est aussi un objet comme un autre : on peut la stocker dans une variable, la passer en argument, la renvoyer. Cette propriété ouvre la porte aux décorateurs qu'on verra au chapitre 8.
def aire_rectangle(largeur, hauteur):
"""Renvoie l'aire d'un rectangle."""
return largeur * hauteur
aire_rectangle(3, 4) # 12Sans return, une fonction renvoie None. La chaîne sous la signature est une docstring, lisible via help(aire_rectangle).
def saluer(nom, salutation="Bonjour", ponctuation="!"):
return f"{salutation} {nom}{ponctuation}"
saluer("Ada") # 'Bonjour Ada!'
saluer("Ada", "Salut") # 'Salut Ada!'
saluer("Ada", ponctuation=".") # 'Bonjour Ada.'La valeur par défaut est évaluée une seule fois, à la définition de la fonction.
def ajouter(item, liste=[]): # bug
liste.append(item)
return liste
ajouter(1) # [1]
ajouter(2) # [1, 2] — la même liste est réutiliséeLa correction standard :
def ajouter(item, liste=None):
if liste is None:
liste = []
liste.append(item)
return liste*args capture les arguments positionnels en surplus dans un tuple, **kwargs les arguments nommés dans un dict.
def log(niveau, *messages, **contexte):
print(niveau, " ".join(messages), contexte)
log("INFO", "Serveur", "démarré", port=8000, env="prod")
# INFO Serveur démarré {'port': 8000, 'env': 'prod'}Les mêmes opérateurs servent à déplier à l'appel :
coords = (3, 4)
options = {"salutation": "Hey"}
aire_rectangle(*coords)
saluer("Ada", **options)/ marque la fin des paramètres positionnels uniquement, * le début des paramètres nommés uniquement.
def creer_user(id, /, nom, *, admin=False):
...
creer_user(1, "Ada", admin=True) # OK
creer_user(1, "Ada", True) # TypeError : admin doit être nommé
creer_user(id=1, nom="Ada") # TypeError : id est positionnel seulementRendre les booléens nommés obligatoires évite les appels illisibles comme envoyer(msg, True, False).
Python cherche un nom dans cet ordre : Local, Enclosing (fonction englobante), Global (module), Built-in.
x = "global"
def externe():
x = "englobant"
def interne():
print(x) # 'englobant'
interne()Pour réassigner une variable d'une portée supérieure, il faut nonlocal ou global. En pratique, global est un signal de mauvaise conception.
def compteur():
n = 0
def incrementer():
nonlocal n
n += 1
return n
return incrementer
c = compteur()
c() # 1
c() # 2incrementer garde une référence vers n même après la fin de compteur : c'est une closure.
def double(x): return x * 2
def carre(x): return x ** 2
operations = {"double": double, "carre": carre}
operations["carre"](5) # 25
def appliquer(f, valeurs):
return [f(v) for v in valeurs]
appliquer(double, [1, 2, 3]) # [2, 4, 6]Une lambda est une fonction anonyme limitée à une expression. Son usage principal : les clés de tri.
users = [{"nom": "Linus", "age": 55}, {"nom": "Ada", "age": 36}]
sorted(users, key=lambda u: u["age"])
max(users, key=lambda u: u["age"])["nom"] # 'Linus'Si la lambda dépasse une ligne ou mérite un nom, écrivez un def.
def factorielle(n):
return 1 if n <= 1 else n * factorielle(n - 1)Python n'optimise pas la récursion terminale et limite la profondeur à 1000 appels par défaut. Pour parcourir un arbre, la récursion est parfaite. Pour boucler 100 000 fois, préférez une boucle.
def aire_rectangle(largeur: float, hauteur: float) -> float:
return largeur * hauteurLes annotations ne sont pas vérifiées à l'exécution. Elles documentent et permettent à un outil comme mypy de détecter les erreurs. Le chapitre 9 y est consacré.
Écrire stats(*nombres) qui renvoie un tuple (min, max, moyenne), et lève une ValueError si aucun nombre n'est passé.
def stats(*nombres: float) -> tuple[float, float, float]:
if not nombres:
raise ValueError("Au moins un nombre requis")
return min(nombres), max(nombres), sum(nombres) / len(nombres)
mini, maxi, moy = stats(4, 8, 15, 16, 23, 42)Les fonctions Python sont des objets de première classe. Closures, fonctions passées en argument, arguments nommés obligatoires : ce trio suffit à écrire du code propre et déjà très modulaire.