J'ai donc du mal avec le concept de *args
et **kwargs
.
Jusqu'à présent, j'ai appris que:
*args
= liste d'arguments - en tant qu'arguments de position**kwargs
= dictionnaire - dont les clés deviennent des arguments de mot clé distincts et les valeurs deviennent des valeurs de ces arguments.Je ne comprends pas quelle tâche de programmation cela pourrait être utile.
Peut être:
Je pense entrer des listes et des dictionnaires en tant qu'arguments d'une fonction ET en même temps qu'un caractère générique, afin que je puisse passer AUCUN argument?
Existe-t-il un exemple simple expliquant comment *args
et **kwargs
sont utilisés?
Aussi, le tutoriel que j'ai trouvé utilisait uniquement le "*" et un nom de variable.
Est-ce que *args
et **kwargs
ne sont que des espaces réservés ou utilisez-vous exactement *args
et **kwargs
dans le code?
La syntaxe est la suivante: *
et **
. Les noms *args
et **kwargs
ne sont que par convention, mais il n’est pas nécessaire de les utiliser.
Vous utiliserez *args
lorsque vous ne savez pas combien d'arguments peuvent être transmis à votre fonction, c'est-à-dire que cela vous permet de transmettre un nombre arbitraire d'arguments à votre fonction. Par exemple:
>>> def print_everything(*args):
for count, thing in enumerate(args):
... print( '{0}. {1}'.format(count, thing))
...
>>> print_everything('Apple', 'banana', 'cabbage')
0. Apple
1. banana
2. cabbage
De même, **kwargs
vous permet de gérer des arguments nommés que vous n'avez pas définis à l'avance:
>>> def table_things(**kwargs):
... for name, value in kwargs.items():
... print( '{0} = {1}'.format(name, value))
...
>>> table_things(Apple = 'fruit', cabbage = 'vegetable')
cabbage = vegetable
Apple = fruit
Vous pouvez aussi les utiliser avec des arguments nommés. Les arguments explicites obtiennent d’abord des valeurs, puis tout le reste est passé à *args
et **kwargs
. Les arguments nommés viennent en premier dans la liste. Par exemple:
def table_things(titlestring, **kwargs)
Vous pouvez également utiliser les deux dans la même définition de fonction, mais *args
doit apparaître avant **kwargs
.
Vous pouvez également utiliser la syntaxe *
et **
pour appeler une fonction. Par exemple:
>>> def print_three_things(a, b, c):
... print( 'a = {0}, b = {1}, c = {2}'.format(a,b,c))
...
>>> mylist = ['aardvark', 'baboon', 'cat']
>>> print_three_things(*mylist)
a = aardvark, b = baboon, c = cat
Comme vous pouvez le constater dans ce cas, il faut la liste (ou le nuplet) d’articles et le décompresse. En cela, il les associe aux arguments de la fonction. Bien sûr, vous pourriez avoir un *
à la fois dans la définition de la fonction et dans l'appel de la fonction.
Un endroit où l'utilisation de *args
et **kwargs
est très utile est celui du sous-classement.
class Foo(object):
def __init__(self, value1, value2):
# do something with the values
print value1, value2
class MyFoo(Foo):
def __init__(self, *args, **kwargs):
# do something else, don't care about the args
print 'myfoo'
super(MyFoo, self).__init__(*args, **kwargs)
De cette façon, vous pouvez étendre le comportement de la classe Foo sans avoir à en savoir trop sur Foo. Cela peut être très pratique si vous programmez une API susceptible de changer. MyFoo passe juste tous les arguments à la classe Foo.
Voici un exemple qui utilise 3 types de paramètres différents.
def func(required_arg, *args, **kwargs):
# required_arg is a positional-only parameter.
print required_arg
# args is a Tuple of positional arguments,
# because the parameter name has * prepended.
if args: # If args is not empty.
print args
# kwargs is a dictionary of keyword arguments,
# because the parameter name has ** prepended.
if kwargs: # If kwargs is not empty.
print kwargs
>>> func()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: func() takes at least 1 argument (0 given)
>>> func("required argument")
required argument
>>> func("required argument", 1, 2, '3')
required argument
(1, 2, '3')
>>> func("required argument", 1, 2, '3', keyword1=4, keyword2="foo")
required argument
(1, 2, '3')
{'keyword2': 'foo', 'keyword1': 4}
Voici l'un de mes endroits préférés pour utiliser la syntaxe **
comme dans le dernier exemple de Dave Webb:
mynum = 1000
mystr = 'Hello World!'
print "{mystr} New-style formatting is {mynum}x more fun!".format(**locals())
Je ne sais pas si c'est terriblement rapide par rapport à l'utilisation des noms eux-mêmes, mais il est beaucoup plus facile de taper!
Un cas où * args et ** kwargs sont utiles est lors de l'écriture de fonctions d'encapsulation (telles que les décorateurs) qui doivent pouvoir accepter des arguments arbitraires à transmettre à la fonction encapsulée. Par exemple, un simple décorateur qui imprime les arguments et renvoie la valeur de la fonction encapsulée:
def mydecorator( f ):
@functools.wraps( f )
def wrapper( *args, **kwargs ):
print "Calling f", args, kwargs
v = f( *args, **kwargs )
print "f returned", v
return v
return wrapper
* args et ** kwargs sont des fonctionnalités spéciales de Python. Pensez à une fonction qui pourrait avoir un nombre inconnu d’arguments. Par exemple, pour quelque raison que ce soit, vous voulez une fonction qui additionne un nombre inconnu de nombres (et vous ne voulez pas utiliser la fonction de somme intégrée). Donc, vous écrivez cette fonction:
def sumFunction(*args):
result = 0
for x in args:
result += x
return result
et l'utiliser comme: sumFunction (3,4,6,3,6,8,9).
** Kwargs a une fonction différente. Avec ** kwargs, vous pouvez donner des arguments de mot-clé arbitraires à une fonction et y accéder en tant que dicton.
def someFunction(**kwargs):
if 'text' in kwargs:
print kwargs['text']
L'appel à someFunction (text = "foo") imprimera foo.
Imaginez que vous ayez une fonction mais que vous ne vouliez pas limiter le nombre de paramètres requis. Exemple:
>>> import operator
>>> def multiply(*args):
... return reduce(operator.mul, args)
Ensuite, vous utilisez cette fonction comme:
>>> multiply(1,2,3)
6
or
>>> numbers = [1,2,3]
>>> multiply(*numbers)
6
Les noms *args
et **kwargs
ou **kw
sont purement conventionnels. Cela nous facilite la lecture du code de chacun
Un endroit pratique pour utiliser le module struct
struct.unpack()
renvoie un tuple alors que struct.pack()
utilise un nombre variable d'arguments. Lors de la manipulation de données, il est pratique de pouvoir passer un Tuple à struck.pack()
par exemple.
Tuple_of_data = struct.unpack(format_str, data)
... manipulate the data
new_data = struct.pack(format_str, *Tuple_of_data)
sans cette capacité, vous seriez obligé d'écrire
new_data = struct.pack(format_str, Tuple_of_data[0], Tuple_of_data[1], Tuple_of_data[2],...)
ce qui signifie également que si le format_str change et que la taille du tuple change, je vais devoir revenir en arrière et éditer cette très longue ligne
Notez que * args/** kwargs fait partie de la syntaxe d'appel de fonction et n'est pas vraiment un opérateur. J'ai eu un effet secondaire particulier, à savoir que vous ne pouvez pas utiliser l'extension * args avec l'instruction print, car print n'est pas une fonction.
Cela semble raisonnable:
def myprint(*args):
print *args
Malheureusement, il ne compile pas (erreur de syntaxe).
Cela compile:
def myprint(*args):
print args
Mais affiche les arguments sous forme de tuple, ce qui n'est pas ce que nous voulons.
C'est la solution sur laquelle j'ai choisi:
def myprint(*args):
for arg in args:
print arg,
print
Ces paramètres sont généralement utilisés pour les fonctions de proxy, de sorte que le proxy peut transmettre n'importe quel paramètre d'entrée à la fonction cible.
def foo(bar=2, baz=5):
print bar, baz
def proxy(x, *args, **kwargs): # reqire parameter x and accept any number of additional arguments
print x
foo(*args, **kwargs) # applies the "non-x" parameter to foo
proxy(23, 5, baz='foo') # calls foo with bar=5 and baz=foo
proxy(6)# calls foo with its default arguments
proxy(7, bar='asdas') # calls foo with bar='asdas' and leave baz default argument
Mais puisque ces paramètres cachent les noms de paramètres réels, il est préférable de les éviter.
Vous pouvez consulter python docs (docs.python.org dans la FAQ), mais plus précisément pour une bonne explication les mystérieuses miss args et mister kwargs (avec la permission de archive.org) (le lien mort original est ici ).
En un mot, les deux sont utilisés lorsque des paramètres optionnels d’une fonction ou d’une méthode sont utilisés. Comme Dave le dit, * args est utilisé quand vous ne savez pas combien d'arguments peuvent être passés, et ** kwargs quand vous voulez gérer les paramètres spécifiés par nom et valeur comme dans:
myfunction(myarg=1)