Comprendre *args
et **kwargs
en Python
En Python, *args
et **kwargs
permettent de passer un nombre variable d’arguments à une fonction. Voici une explication détaillée :
*args
- Utilisation :
*args
permet de recevoir un nombre variable d’arguments positionnels.
- Fonctionnement : Les arguments passés après le paramètre formel marqué par
*args
sont collectés dans un tuple.
Exemple :
def addition(*args):
total = 0
for nombre in args:
total += nombre
return total
print(addition(1, 2, 3)) # Affiche 6
print(addition(10, 20)) # Affiche 30
Dans cet exemple, *args
recueille tous les arguments positionnels (1, 2, 3
ou 10, 20
) dans le tuple args
.
**kwargs
- Utilisation :
**kwargs
permet de recevoir un nombre variable d’arguments nommés (keyword arguments).
- Fonctionnement : Les arguments passés après le paramètre formel marqué par
**kwargs
sont collectés dans un dictionnaire où les clés sont les noms des paramètres et les valeurs sont les valeurs correspondantes.
Exemple :
def afficher_info(**kwargs):
for cle, valeur in kwargs.items():
print(f"{cle} : {valeur}")
afficher_info(nom="Alice", age=30, ville="Paris")
Ici, **kwargs
recueille les arguments nommés dans un dictionnaire :
"nom": "Alice"
"age": 30
"ville": "Paris"
Combinaison de *args
et **kwargs
Vous pouvez utiliser les deux dans une même fonction pour gérer à la fois des arguments positionnels et nommés. Il est important de noter que *args
doit apparaître avant **kwargs
.
def fonction_mixte(*args, **kwargs):
print("Arguments positionnels:", args)
print("Arguments nommés:", kwargs)
fonction_mixte(1, 2, 3, a=4, b=5)
Ce code affichera :
- Arguments positionnels:
(1, 2, 3)
- Arguments nommés:
{'a': 4, 'b': 5}
Conclusion
- Utilité : Ces mécanismes rendent vos fonctions plus flexibles en permettant d’accepter un nombre variable d’arguments.
- Bonne pratique : Utilisez-les lorsque vous ne savez pas exactement combien d’arguments seront fournis ou pour créer des interfaces génériques.
Ainsi, *args
et **kwargs
sont des outils très puissants pour écrire des fonctions modulables et réutilisables en Python.
Exemple avancé d'utilisation de *args
dans une fonction
Pour illustrer la puissance de *args
dans un cas concret, prenons l'exemple d'un script qui effectue un traitement de texte sur plusieurs fichiers. Cette fonction remplace un mot par un autre dans tous les fichiers passés en argument.
Extrait adapté du tutoriel Python de Alexandre GALODE, disponible sur
developpez.com :
# Avec *args
def traitement(a_remplacer, remplacant, *args):
for idx, fichier in enumerate(args):
content = ""
with open(fichier, 'r') as fichier_only:
for line in fichier_only.readlines():
line = line.replace(a_remplacer, remplacant)
content += line
with open(fichier, 'w') as fichier_only:
fichier_only.write(content)
if __name__ == '__main__':
traitement('riri', 'fifi', 'fichier1.txt')
traitement('toto', 'tata', 'fichier1.txt', 'fichier2.txt', 'fichiern.txt') # le nombre d'arguments est variable
liste_fichiers=['fichier3.txt', 'fichier4.txt', 'fichiers5.txt']
traitement('fifi', 'loulou', *liste_fichiers) # passage d'une liste grâce à l'opérateur *
Grâce à *args
, la fonction traitement
peut manipuler dynamiquement un nombre quelconque de fichiers texte, qu'ils soient passés directement ou via une liste. Cela rend le script extrêmement flexible et adapté à une grande variété de scénarios.
Utilisation de **kwargs
pour initialiser dynamiquement un objet
Une autre application très pratique de **kwargs
est l'initialisation dynamique d’un objet. Cela permet de créer des instances d’une classe en passant un nombre variable d’attributs lors de la construction.
Voici un exemple avec une classe User
:
class User:
def __init__(self, **kwargs):
for key, value in kwargs.items():
setattr(self, key, value)
utilisateur = User(prenom="Patrick", nom="Smith", age=30)
print(utilisateur.prenom, utilisateur.nom, utilisateur.age)
utilisateur2 = User(prenom="Luigi", age=25, nationalite="Italien")
print(utilisateur2.prenom, utilisateur2.age, utilisateur2.nationalite)
Dans cet exemple :
- Le constructeur
__init__
de la classe User
accepte n’importe quel nombre d’attributs nommés grâce à **kwargs
.
- La fonction
setattr
est utilisée pour créer dynamiquement chaque attribut de l’objet avec la clé et la valeur fournies.
Ce qui est affiché :
Patrick Smith 30
Luigi 25 Italien
Ce pattern est particulièrement utile dans les cas où les attributs d’un objet peuvent varier selon le contexte d’utilisation, comme lors de la manipulation de données JSON ou de formulaires dynamiques.
Combiner *args
et **kwargs
dans une fonction
Il est possible de combiner *args
et **kwargs
dans une même fonction pour gérer à la fois des arguments positionnels et des arguments nommés. Voici deux exemples illustrant cette flexibilité :
Exemple 1 : Affichage des deux types d’arguments
def example_function(*args, **kwargs):
print("Positional arguments:", args)
print("Keyword arguments:", kwargs)
example_function(1, 2, 3, a="apple", b="banana")
Output:
Positional arguments: (1, 2, 3)
Keyword arguments: {'a': 'apple', 'b': 'banana'}
Ici, la fonction reçoit :
- Des arguments positionnels : collectés dans
args
sous forme de tuple.
- Des arguments nommés : collectés dans
kwargs
sous forme de dictionnaire.
Exemple 2 : Personnalisation d’un message de salutation
def greet(name, *args, **kwargs):
greeting = kwargs.get('greeting', 'Hello')
print(f"{greeting}, {name}!")
if args:
print("Additional names:", ', '.join(args))
greet("Alice")
greet("Alice", "Bob", "Charlie", greeting="Hi")
Output:
Hello, Alice!
Hi, Alice!
Additional names: Bob, Charlie
Ce second exemple montre :
- Comment récupérer une valeur spécifique dans
kwargs
à l’aide de .get()
, avec une valeur par défaut si l’argument est absent.
- Comment afficher les noms supplémentaires passés en positionnel après le premier argument obligatoire.
Grâce à cette combinaison, vous pouvez créer des fonctions extrêmement souples, capables de s’adapter à un grand nombre de cas d’utilisation.