web-dev-qa-db-fra.com

Utilisation de * args et ** kwargs

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?

1340
MacPython

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.

1610
Dave Webb

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.

470
Mark van Lent

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}
306
Kit

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!

71
Wayne Werner

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
43
jchl

* 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.

36
Steven Mohr

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
18
Felix Kling

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

16
John La Rooy

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
9
yoyo

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.

7
Rudi

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)
3
Yoni H