Jusqu'ici, vos fonctions avaient un nombre fixe de paramètres. Python permet de faire mieux : des fonctions qui acceptent un nombre variable d'arguments, positionnels ou nommés. C'est ce que permettent *args et **kwargs — deux constructions très fréquentes dans le code Python réel.
Le problème : un nombre variable d'arguments
Imaginez une fonction additionner qui doit fonctionner pour 2 nombres, 3, 10... sans qu'on connaisse le nombre à l'avance.
# ❌ Solution limitée : un paramètre par argument
def additionner(a, b):
return a + b
print(additionner(1, 2))
# print(additionner(1, 2, 3)) # TypeError !Ou alors on passe une liste, mais l'appel est moins pratique :
def additionner(nombres):
return sum(nombres)
print(additionner([1, 2, 3, 4])) # obligation de mettre la listeIdéalement, on voudrait écrire additionner(1, 2, 3, 4) directement. C'est ce que permet *args.
*args — arguments positionnels variables
Le préfixe * dans la signature collecte tous les arguments positionnels supplémentaires dans un tuple.
def additionner(*args):
return sum(args)
print(additionner(1, 2))
print(additionner(1, 2, 3))
print(additionner(1, 2, 3, 4, 5))
print(additionner()) # aucun argument : 0args est un simple tuple — vous pouvez l'itérer, le mesurer, etc.
def afficher_tout(*args):
print(f"Type : {type(args)}")
print(f"Nombre : {len(args)}")
for i, val in enumerate(args):
print(f" [{i}] {val}")
afficher_tout("Alice", 30, True, [1, 2])Combiner paramètres fixes et *args
Les paramètres positionnels fixes viennent avant *args.
def rapport(titre, *valeurs):
print(f"=== {titre} ===")
for v in valeurs:
print(f" - {v}")
rapport("Notes", 12, 15, 17, 9)*args est toujours un tuple
Même avec un seul argument :
def f(*args):
print(type(args), args)
f(42)
f(42, 43)
f()**kwargs — arguments nommés variables
Le préfixe ** collecte tous les arguments nommés supplémentaires dans un dictionnaire.
def afficher_infos(**kwargs):
for cle, valeur in kwargs.items():
print(f" {cle} = {valeur}")
afficher_infos(nom="Alice", age=30, ville="Paris")Exemple : fabriquer un URL avec paramètres
def construire_url(base, **params):
if not params:
return base
query = "&".join(f"{k}={v}" for k, v in params.items())
return f"{base}?{query}"
print(construire_url("http://api.fr/search"))
print(construire_url("http://api.fr/search", q="python", page=2))
print(construire_url("http://api.fr/search", user="alice", limit=50, sort="date"))**kwargs est toujours un dict
def f(**kwargs):
print(type(kwargs), kwargs)
f(a=1, b=2)
f()