Introduction
En débutant en Python, on rencontre des exemples de code avec les syntaxes suivantes :
def log_error(self, msg, *args, **kwargs)
- Habitué à Javascript, PHP…, on se demande :
*args,**kwargs, c’est quoi ça ? - Habitué des langages C ou Go, on se demande :
*args,**kwargs, des pointeurs en Python ?
*args et **kwargs permettent de passer de multiples arguments et des arguments nommés à une fonction.
Expliquons *args et **kwargs à travers des exemples simples.
Une simple fonction qui retourne une somme, args
argkarg.py
def sum(x,y):
return x + y
print(sum(1,2))
$ python3 argkarg.py3
Cette fonction fonctionne à merveille si il n’y a que 2 arguments entiers.
*args est utilisé pour spécifier de multiples arguments :
argkarg.py
def sum(*args): r = 0 for x in args: r += x return r print(sum(10,20,30,40))100
args est juste un nom, un autre nom peut être utilisé :
def sum(*listint):
r = 0
for x in listint:
…
L’opérateur * est important ici.
args dans la fonction est alors un objet de type tuple, ce n’est pas un objet list.
Les objets de type tuple sont immutables, les valeurs ne peuvent plus être modifiées après définition.
def sum(*args): print(args) print(type(args)) r = 0 for x in args: r += x return r print(sum(10,20,30,40))(10, 20, 30, 40) <class 'tuple'> 100
Utiliser également l’opérateur * si les valeurs des arguments sont stockées dans des objets list ou tuple :
l = [10,20,30,40] print(sum(*l)) t = [100,200,300,400] print(sum(*t))100 1000
kwargs dans les fonctions
**kwargs fonctionne comme *args mais pour les arguments nommés (kw pour keyword).
def sum(**kwargs): r = 0 for x in kwargs.values(): r += x return r print(sum(a=10,b=20,c=30,d=40))100
Comme args, kwargs est juste un nom, il peut être différent.
L’opérateur ** conduit à un dictionnaire, mutable. kwargs est un dictionnaire :
def sum(**kwargs): print(kwargs) print(type(kwargs)) r = 0 for x in kwargs.values(): r += x return r print(sum(a=10,b=20,c=30,d=40))<class 'dict'> {'a': 10, 'b': 20, 'c': 30, 'd': 40} 100
Combiner args et kwargs, ordre des arguments
L’ordre des arguments est important dans la déclaration de la fonction
lorsque *args et **kwargs sont à la fois utilisés :
- Arguments réguliers
- Arguments
*args - Arguments
**kwargs
def sum(x,y,*args,**kwargs): r=0 r = x + y for i in args: r += i for i in kwargs.values(): r += i return r print(sum(1,2,3,4,a=10,b=20,c=30,d=40))110
Une erreur "Invalid syntax" est levée lorsque l’ordre n’est pas le bon :
def sum(x,y,**kwargs,*args): …File "argkarg.py", line 15 def sum(x,y,**kwargs,*args): ^ SyntaxError: invalid syntax
Les opérateurs * et ** (unpacking operators)
L’opérateur * défait les objets itérables : listes, tuples
l = [1,2,3] print(*l) t = (1,2,3) print(*t)1 2 3 1 2 3
Cet opérateur * est très utile pour fusionner des listes et/ou des tuples, un exemple :
t1 = (1,2,3) t2 = (4,5) l1 = [6,7] t3 = (*t1,*t2,*l1) l2 = [*t1,*t2,*l1] print(t3) print(l2)(1, 2, 3, 4, 5, 6, 7) [1, 2, 3, 4, 5, 6, 7]
L’opérateur ** défait les dictionnaires, utile pour fusionner des dictionnaires :
d1 = { 'a' : 10, 'b' : 20 } d2 = { 'c' : 30, 'd' : 40 } d3 = { **d1, **d2 } print(d3){'a': 10, 'b': 20, 'c': 30, 'd': 40}