64 votes

Pourquoi utiliser **kwargs en python? Ce sont quelques vrais avantages par rapport à l'aide d'arguments nommés?

Je viens d'un milieu statique langues. Quelqu'un peut m'expliquer (espérons-le, par exemple), le monde réel avantages de l'utilisation **kwargs sur les arguments nommés? Pour moi, ils semblent seulement faire l'appel de fonction plus ambigu. Merci.

61voto

Alex Martelli Points 330805

Voulez-vous accepter presque arbitraire des arguments nommés pour une série de raisons, et c'est ce que l' **kw formulaire vous permet de le faire.

La raison la plus commune est de passer les arguments à droite sur une autre fonction vous êtes d'emballage (décorateurs sont un cas, mais LOIN d'être la seule!) - dans ce cas, **kw desserre le couplage entre l'enveloppe et wrappee, que l'emballage ne doit pas savoir ou de soins sur l'ensemble de la wrappee arguments. En voici un autre, complètement différente raison:

d = dict(a=1, b=2, c=3, d=4)

si tous les noms avaient à être connu à l'avance, alors il est évident que cette approche ne pouvait pas exister, non? Et btw, le cas échéant, je préfère de beaucoup cette façon de faire un dictionnaire dont les clés sont des chaînes de caractères littérales à:

d = {'a': 1, 'b': 2, 'c': 3, 'd': 4}

tout simplement parce que ce dernier est assez ponctuation-lourds et donc moins lisible.

Lorsque aucun des excellentes raisons d'accepter **kwargs s'applique, alors ne pas l'accepter: c'est aussi simple que cela. OIE, si il n'y a pas de bonne raison de permettre à l'appelant de passe supplémentaire nommé args arbitraire de noms, ne pas permettre que cela arrive -- juste éviter de mettre un **kw à la fin de la fonction de la signature de l' def déclaration.

Comme pour l'aide d' **kw dans un appel, qui vous permet de mettre ensemble l'ensemble exact des arguments nommés que vous devez passer, chacun avec des valeurs correspondantes, dans un dict, indépendamment d'un seul point d'appel, puis utiliser ce dict à l'appel de point. Comparer:

if x: kw['x'] = x
if y: kw['y'] = y
f(**kw)

pour:

if x:
  if y:
    f(x=x, y=y)
  else:
    f(x=x)
else:
  if y:
    f(y=y)
  else:
    f()

Même avec seulement deux possibilités (et de la très simples!), le manque d' **kw est aleady la seconde option absolument intenable et insupportable -- imaginez comment il joue quand il y a une demi-douzaine de possibilités, peut-être dans un peu plus riches de l'interaction... sans **kw, la vie serait absolue de l'enfer dans de telles circonstances!

40voto

Daniel Roseman Points 199743

Une autre raison, vous pourriez vouloir utiliser **kwargs (et *args) est si vous êtes extension d'une méthode dans une sous-classe. Vous souhaitez passer tous les arguments sur la super-classe de la méthode, mais vous voulez vous assurer que votre classe continue de travailler même si les changements de signature dans une version ultérieure:

class MySubclass(Superclass):
    def __init__(self, *args, **kwargs):
        self.myvalue = kwargs.pop('myvalue', None)
        super(MySubclass, self).__init__(*args, **kwargs)

38voto

Cat Plus Plus Points 53385

Des exemples du monde réel:

Décorateurs - en général, elles sont génériques, de sorte que vous ne pouvez pas spécifier les arguments initiaux:

def decorator(old):
    def new(*args, **kwargs):
        # ...
        return old(*args, **kwargs)
    return new

Lieux où vous souhaitez vous faire de la magie avec un nombre inconnu de mot-clé arguments. L'ORM de Django n'est que, par exemple:

Model.objects.filter(foo__lt = 4, bar__iexact = 'bar')

11voto

Ned Batchelder Points 128913

Il y a deux cas de figures:

Première: Vous êtes d'emballage une autre fonction qui prend un certain nombre d'argument mot-clé, mais vous allez juste pour les transmettre:

def my_wrapper(a, b, **kwargs):
    do_something_first(a, b)
    the_real_function(**kwargs)

Deuxièmement: Vous êtes prêt à accepter tout argument mot-clé, par exemple, pour définir les attributs d'un objet:

class OpenEndedObject:
    def __init__(self, **kwargs):
        for k, v in kwargs.items():
            setattr(self, k, v)

foo = OpenEndedObject(a=1, foo='bar')
assert foo.a == 1
assert foo.foo == 'bar'

4voto

Cristian Ciupitu Points 5692

**kwargs sont bonnes si vous ne savez pas à l'avance le nom des paramètres. Par exemple, l' dict constructeur utilise pour initialiser les clés du nouveau dictionnaire.

dict(**kwargs) -> new dictionary initialized with the name=value pairs
    in the keyword argument list.  For example:  dict(one=1, two=2)
In [3]: dict(one=1, two=2)
Out[3]: {'one': 1, 'two': 2}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X