Menu
Français

Python *args et **kwargs : arguments positionnels et nommés flexibles

Ce que signifient *args et **kwargs, quand les utiliser, et comment transférer des arguments proprement entre fonctions.

Quand tu ne sais pas combien d'arguments il y aura

La plupart des fonctions prennent un nombre fixe de paramètres. Mais occasionnellement, tu as besoin de quelque chose de plus flexible — un logger qui prend un nombre quelconque de messages, une fonction wrapper qui transfère ce qu'elle a reçu à une autre fonction, une fonction de tracé qui accepte une configuration sans savoir exactement quelles options l'appelant va utiliser.

Python gère ça avec deux marqueurs spéciaux dans la liste de paramètres : *args et **kwargs.

*args collecte les arguments positionnels

Une seule étoile dit « emballe tous les arguments positionnels supplémentaires dans un tuple » :

main.py
Output
Click Run to see the output here.

À l'intérieur de la fonction, args est un tuple normal. Tu peux boucler dessus, l'indexer, le passer à len() ou le découper.

*args apparaît généralement aux côtés de paramètres nommés :

main.py
Output
Click Run to see the output here.

first attrape le premier argument ; *rest empaquete tout ce qui suit dans un tuple.

**kwargs collecte les arguments nommés

Deux étoiles font l'équivalent pour les arguments nommés, en les empaquant dans un dict :

main.py
Output
Click Run to see the output here.

À l'intérieur de describe, kwargs est un dict normal. Les clés sont les noms des mots-clés sous forme de chaînes.

Les utiliser ensemble

Tu peux utiliser les deux dans la même fonction. La convention, c'est *args avant **kwargs :

main.py
Output
Click Run to see the output here.

L'ordre complet des paramètres, de gauche à droite, c'est :

  1. Paramètres positionnels normaux (requis ou avec défauts).
  2. *args.
  3. Paramètres keyword-only (tout après *args doit être passé par nom).
  4. **kwargs.
main.py
Output
Click Run to see the output here.

title attrape le premier positionnel. Le reste des positionnels va dans tags. draft doit être passé par nom (il vient après *tags). Les autres arguments nommés atterrissent dans metadata.

Déballer avec * et ** au site d'appel

Les étoiles marchent aussi à l'envers — en étalant une séquence ou un dict dans les arguments d'un appel :

main.py
Output
Click Run to see the output here.

C'est incroyablement pratique pour transférer des arguments :

main.py
Output
Click Run to see the output here.

wrapped n'a pas besoin de savoir quels arguments log attend. Il collecte tout et le transmet. Ce motif apparaît sans arrêt dans les décorateurs (un sujet plus avancé) et les fonctions wrapper.

Quand *args et **kwargs sont le mauvais choix

Il est facile de s'emballer et de les utiliser partout. Deux avertissements :

Ils cachent ce qu'une fonction attend

Si chaque fonction de ta base de code est def f(*args, **kwargs), le code appelant n'a aucune idée des arguments valides. Utilise des paramètres nommés quand tu peux, et laisse *args/**kwargs ne porter que des entrées vraiment variables ou du transfert pur.

Les messages d'erreur deviennent vagues

Un nom de mot-clé mal tapé devient un None silencieux ou un KeyError profondément dans la fonction, au lieu d'un « argument mot-clé inattendu » immédiat au site d'appel. Les paramètres nommés te donnent un bien meilleur feedback.

En règle générale : préfère les paramètres nommés par défaut, et utilise *args/**kwargs seulement quand la fonction est vraiment flexible ou qu'elle transfère des arguments à un autre appelable.

Un petit exemple pratique

Un helper de style tracé qui enveloppe une fonction tierce avec quelques défauts :

main.py
Output
Click Run to see the output here.

Le *values laisse les appelants passer n'importe quel nombre d'éléments ; **style absorbe la configuration supplémentaire sans exiger que chaque option soit un paramètre nommé. C'est flexible sans être opaque, parce que la logique interne te dit exactement quelles clés elle lit dans style.

Récap

  • *args empaque les arguments positionnels supplémentaires dans un tuple.
  • **kwargs empaque les arguments nommés supplémentaires dans un dict.
  • Au site d'appel, *seq et **dict déballent dans l'autre direction.
  • Les paramètres doivent apparaître dans l'ordre : normal → *args → keyword-only → **kwargs.
  • Ne surutilise pas — les paramètres nommés sont plus clairs quand tu peux les utiliser.

Ensuite : lambda, une façon d'écrire de minuscules fonctions jetables en ligne.

Questions fréquentes

Qu'est-ce que *args en Python ?

*args collecte tous les arguments positionnels supplémentaires dans un tuple. def f(*args): te permet d'appeler f(1, 2, 3) et de recevoir args comme (1, 2, 3). Le nom args est une convention — tu pourrais l'appeler autrement, mais *args est ce que tout le monde utilise.

Qu'est-ce que **kwargs en Python ?

**kwargs collecte tous les arguments nommés supplémentaires dans un dict. def f(**kwargs): te permet d'appeler f(name='Ada', age=30) et de recevoir kwargs comme {'name': 'Ada', 'age': 30}. Ensemble, *args et **kwargs permettent à une fonction d'accepter n'importe quelle combinaison d'arguments.

Dois-je les nommer args et kwargs ?

Non, ce sont les étoiles qui comptent, pas les noms. *values et **options marchent à l'identique. Mais args et kwargs sont une convention quasi universelle dans le code Python — tiens-t'y, sauf raison particulière de choisir quelque chose de plus descriptif.

Apprendre à coder avec Coddy

COMMENCER