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.py
3
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}