Aller au contenu

Les kwargs

Introduction

En Python, une fonction peut recevoir un nombre variable d'arguments nommés grâce à la syntaxe **kwargs (prononcé "ké-wargz"). Ces arguments sont regroupés dans un dictionnaire dont les clés correspondent aux noms des arguments et les valeurs aux données transmises.

Le nom kwargs est une convention, issue de keyword arguments. Dans la signature d'une fonction, le préfixe ** permet d'accepter les arguments nommés, qui ne correspondent pas à des paramètres explicites.

Déclarer et appeler une fonction

Voici une fonction qui affiche les données reçues sous forme d'arguments nommés :

def display_information(**kwargs):
    for name, value in kwargs.items():
        print(f"{name} : {value}")

Nous pouvons l'appeler avec différents arguments nommés :

display_information(name="Clavier", price=69.79)

Résultat :

name : Clavier
price : 69.79

Dans la fonction, kwargs contient le dictionnaire suivant :

{"name": "Clavier", "price": 69.79}

Nous pouvons également appeler cette fonction sans argument. Le dictionnaire sera alors vide.

Combiner paramètres explicites et kwargs

Une fonction peut déclarer des paramètres explicites et utiliser **kwargs pour recueillir les arguments nommés supplémentaires :

def describe_product(name: str, **kwargs):
    print(f"Produit : {name}")

    if "price" in kwargs:
        print(f"Prix : {kwargs['price']:.2f} €")

    category = kwargs.get("category", "Non précisée")
    print(f"Catégorie : {category}")

Exemple d'appel de cette fonction :

describe_product(
    name="Clavier",
    price=69.79,
    category="Informatique"
)

L'argument name est associé au paramètre explicite. Seuls price et category sont placés dans le dictionnaire kwargs.

La méthode get permet de récupérer une valeur en fournissant une valeur par défaut lorsque la clé est absente.

Transmettre un dictionnaire avec **

Lors d'un appel, le préfixe ** permet de décomposer un dictionnaire en arguments nommés :

information = {
    "name": "Clavier",
    "price": 69.79,
    "category": "Informatique"
}

describe_product(**information)

Cet appel est équivalent à l'appel précédent. Les clés du dictionnaire doivent être des chaînes de caractères. Ce mécanisme fonctionne aussi avec une fonction qui déclare uniquement des paramètres explicites :

def calculate_total(price: float, quantity: int) -> float:
    return price * quantity

arguments = {"price": 69.79, "quantity": 2}

total = calculate_total(**arguments)
print(total)

Les clés doivent alors correspondre aux paramètres acceptés par la fonction.

Différence entre *args et **kwargs

Les deux syntaxes répondent à des besoins différents :

Syntaxe Arguments recueillis Type obtenu
*args Arguments positionnels supplémentaires Tuple
**kwargs Arguments nommés supplémentaires Dictionnaire

Elles peuvent être combinées :

def display_arguments(*args, **kwargs):
    print(args)
    print(kwargs)

display_arguments(10, 20, name="Clavier", price=69.79)

Résultat :

(10, 20)
{'name': 'Clavier', 'price': 69.79}

Dans la signature, **kwargs doit être placé en dernier.

Comparaison avec le langage C#

En C#, les arguments nommés correspondent à des paramètres déclarés dans la signature de la méthode. Le mot-clé params permet de recevoir un nombre variable d'arguments, mais n'accepte pas automatiquement des arguments nommés supplémentaires.

Pour transmettre des couples nom-valeur variables en C#, nous pouvons utiliser explicitement un dictionnaire tel que Dictionary<string, object>.

Bonnes pratiques

Les paramètres kwargs sont utiles pour recevoir des options variables ou transmettre des arguments à une autre fonction.

Lorsque les paramètres sont connus à l'avance, il est préférable de les déclarer explicitement. Cela rend la signature plus lisible et facilite l'autocomplétion ainsi que l'analyse statique.

Avec l'utilisation de kwargs, un nom incorrect peut être accepté sans provoquer immédiatement une exception. La fonction doit donc vérifier les clés reçues si elle souhaite refuser celles qui sont inconnues.