Comprendre kwargs en Python

à quoi sert **kwargs en Python?

je sais que vous pouvez faire un objects.filter sur une table et passer dans un argument **kwargs .  

puis-je également le faire pour spécifier des deltas de temps comme timedelta(hours = time1) ?

comment ça marche exactement? Est-ce que c'est classe comme "déballage"? Comme a,b=1,2 ?

660
demandé sur Blaise 2009-11-20 12:40:57

10 réponses

vous pouvez utiliser **kwargs pour laisser vos fonctions prendre un nombre arbitraire d'arguments de mots clés ("kwargs" signifie "arguments de mots clés"):

>>> def print_keyword_args(**kwargs):
...     # kwargs is a dict of the keyword args passed to the function
...     for key, value in kwargs.iteritems():
...         print "%s = %s" % (key, value)
... 
>>> print_keyword_args(first_name="John", last_name="Doe")
first_name = John
last_name = Doe

vous pouvez également utiliser la syntaxe **kwargs lorsque vous appelez des fonctions en construisant un dictionnaire d'arguments de mots clés et en le passant à votre fonction:

>>> kwargs = {'first_name': 'Bobby', 'last_name': 'Smith'}
>>> print_keyword_args(**kwargs)
first_name = Bobby
last_name = Smith

le tutoriel Python contient une bonne explication de la façon dont il fonctionne, avec quelques nice exemple.

< --Update-->

pour les personnes utilisant Python 3, au lieu de iteritems (), utilisez items ()

754
répondu Pär Wieslander 2018-07-29 23:24:14

dictionnaires de déballage

** dictionnaires non emballés.

Ce

func(a=1, b=2, c=3)

est le même que

args = {'a': 1, 'b': 2, 'c':3}
func(**args)

il est utile si vous devez construire des paramètres:

args = {'name': person.name}
if hasattr(person, "address"):
    args["address"] = person.address
func(**args)  # either expanded to func(name=person.name) or
              #                    func(name=person.name, address=person.address)

paramètres D'emballage d'une fonction

def setstyle(**styles):
    for key, value in styles.iteritems():      # styles is a regular dictionary
        setattr(someobject, key, value)

Cela vous permet d'utiliser la fonction comme ceci:

setstyle(color="red", bold=False)
286
répondu Georg Schölly 2015-08-31 08:34:42

kwargs est juste un dictionnaire qui est ajouté aux paramètres.

un dictionnaire peut contenir des couples de clés et de valeurs. Et ce sont les kwargs. Ok, c'est de cette façon.

le whatfor n'est pas si simple.

par exemple (très hypothétique) vous avez une interface qui appelle simplement d'autres routines pour faire le travail:

def myDo(what, where, why):
   if what == 'swim':
      doSwim(where, why)
   elif what == 'walk':
      doWalk(where, why)
   ...

Maintenant vous obtenez une nouvelle méthode "drive":

elif what == 'drive':
   doDrive(where, why, vehicle)

mais attendez une minute, il y a un nouveau paramètre "véhicule" -- vous ne le connaissiez pas avant. Maintenant, vous devez l'ajouter à la signature de la myDo-fonction.

ici vous pouvez lancer kwargs dans le jeu -- vous ajoutez juste kwargs à la signature:

def myDo(what, where, why, **kwargs):
   if what == 'drive':
      doDrive(where, why, **kwargs)
   elif what == 'swim':
      doSwim(where, why, **kwargs)

de cette façon, vous n'avez pas besoin de changer la signature de votre fonction d'interface chaque fois que certaines de vos routines appelées pourraient changer.

C'est juste un bel exemple, vous pourriez trouver kwargs utile.

59
répondu Juergen 2017-05-04 19:08:44

sur la base du fait qu'un bon échantillon est parfois meilleur qu'un long discours, j'écrirai deux fonctions en utilisant toutes les facilités de passage d'arguments variables python (à la fois des arguments de position et des arguments nommés). Vous devriez facilement être en mesure de voir ce qu'il fait par vous-même:

def f(a = 0, *args, **kwargs):
    print("Received by f(a, *args, **kwargs)")
    print("=> f(a=%s, args=%s, kwargs=%s" % (a, args, kwargs))
    print("Calling g(10, 11, 12, *args, d = 13, e = 14, **kwargs)")
    g(10, 11, 12, *args, d = 13, e = 14, **kwargs)

def g(f, g = 0, *args, **kwargs):
    print("Received by g(f, g = 0, *args, **kwargs)")
    print("=> g(f=%s, g=%s, args=%s, kwargs=%s)" % (f, g, args, kwargs))

print("Calling f(1, 2, 3, 4, b = 5, c = 6)")
f(1, 2, 3, 4, b = 5, c = 6)

et voici la sortie:

Calling f(1, 2, 3, 4, b = 5, c = 6)
Received by f(a, *args, **kwargs) 
=> f(a=1, args=(2, 3, 4), kwargs={'c': 6, 'b': 5}
Calling g(10, 11, 12, *args, d = 13, e = 14, **kwargs)
Received by g(f, g = 0, *args, **kwargs)
=> g(f=10, g=11, args=(12, 2, 3, 4), kwargs={'c': 6, 'b': 5, 'e': 14, 'd': 13})
43
répondu kriss 2016-08-19 01:12:26

Motif: *args et **kwargs est un espace réservé pour les arguments qui doivent être transmis à un appel de fonction

utilisant *args et **kwargs pour appeler une fonction

def args_kwargs_test(arg1, arg2, arg3):
    print "arg1:", arg1
    print "arg2:", arg2
    print "arg3:", arg3

maintenant, nous allons utiliser *args pour appeler la fonction définie ci-dessus

#args can either be a "list" or "tuple"
>>> args = ("two", 3, 5)  
>>> args_kwargs_test(*args)

résultat:

arg1: deux

arg2: 3

arg3: 5


maintenant, en utilisant **kwargs pour appeler la même fonction

#keyword argument "kwargs" has to be a dictionary
>>> kwargs = {"arg3":3, "arg2":'two', "arg1":5}
>>> args_kwargs_test(**kwargs)

résultat:

arg1: 5

arg2: deux

arg3: 3

Bottomline: *args n'a pas d'intelligence, il interpole simplement les args passés aux paramètres (dans l'ordre de gauche à droite) tandis que **kwargs se comporte intelligemment en plaçant la valeur appropriée @ l'endroit désiré

24
répondu kmario23 2016-03-20 14:49:42
  • kwargs dans **kwargs est juste le nom de la variable. Vous pouvez très bien avoir **anyVariableName
  • kwargs signifie" arguments de mots clés". Mais je pense qu'ils devraient plutôt être appelés comme "arguments nommés", car ce sont simplement des arguments transmis avec des noms (Je ne trouve aucune signification au mot" mot-clé "dans le terme"arguments de mots-clés". Je suppose que "mot-clé" signifie habituellement des mots réservés par le langage de programmation et donc ne pas être utilisé par le programmeur pour Noms variables. Rien de Tel ne se produit ici en cas de kwargs.). Alors on donne des noms param1 et param2 à deux valeurs paramétriques transmises à la fonction comme suit: func(param1="val1",param2="val2") , au lieu de passer seulement les valeurs: func(val1,val2) . Ainsi, je pense qu'ils devraient être correctement appelés "nombre arbitraire d'arguments nommés" comme nous pouvons spécifier n'importe quel nombre de ces paramètres (c'est-à-dire, arguments) si func a la signature func(**kwargs)

ainsi dit que permettez-moi d'expliquer "arguments nommés" d'abord et puis "nombre arbitraire d'arguments nommés" kwargs .

les arguments Nommés

  • nommé args devraient suivre de position args
  • l'ordre de named args n'est pas important
  • exemple

    def function1(param1,param2="arg2",param3="arg3"):
        print("\n"+str(param1)+" "+str(param2)+" "+str(param3)+"\n")
    
    function1(1)                      #1 arg2 arg3   #1 positional arg
    function1(param1=1)               #1 arg2 arg3   #1 named arg
    function1(1,param2=2)             #1 2 arg3      #1 positional arg, 1 named arg
    function1(param1=1,param2=2)      #1 2 arg3      #2 named args       
    function1(param2=2, param1=1)     #1 2 arg3      #2 named args out of order
    function1(1, param3=3, param2=2)  #1 2 3         #
    
    #function1()                      #invalid: required argument missing
    #function1(param2=2,1)            #invalid: SyntaxError: non-keyword arg after keyword arg
    #function1(1,param1=11)           #invalid: TypeError: function1() got multiple values for argument 'param1'
    #function1(param4=4)              #invalid: TypeError: function1() got an unexpected keyword argument 'param4'
    

nombre Arbitraire d'arguments nommés kwargs

  • séquence des paramètres de fonction:
    1. paramètres de position
    2. paramètre formel de la capture nombre arbitraire d'arguments (avec le préfixe *)
    3. nommé paramètres formels
    4. paramètre formel capturant le nombre arbitraire de paramètres nommés (préfixé par**)
  • exemple

    def function2(param1, *tupleParams, param2, param3, **dictionaryParams):
        print("param1: "+ param1)
        print("param2: "+ param2)
        print("param3: "+ param3)
        print("custom tuple params","-"*10)
        for p in tupleParams:
            print(str(p) + ",")
        print("custom named params","-"*10)
        for k,v in dictionaryParams.items():
            print(str(k)+":"+str(v))
    
    function2("arg1",
              "custom param1",
              "custom param2",
              "custom param3",
              param3="arg3",
              param2="arg2", 
              customNamedParam1 = "val1",
              customNamedParam2 = "val2"
              )
    
    # Output
    #
    #param1: arg1
    #param2: arg2
    #param3: arg3
    #custom tuple params ----------
    #custom param1,
    #custom param2,
    #custom param3,
    #custom named params ----------
    #customNamedParam2:val2
    #customNamedParam1:val1
    

passer tuple et dict variables for custom args

pour finir, laissez-moi aussi noter que nous pouvons passer

  • "paramètre formel capturant le nombre arbitraire d'arguments" comme tuple variable et
  • " paramètre formel capturant le nombre arbitraire de named paramètres "comme variable dict
  • ainsi, le même appel ci-dessus peut être fait comme suit:

    tupleCustomArgs = ("custom param1", "custom param2", "custom param3")
    dictCustomNamedArgs = {"customNamedParam1":"val1", "customNamedParam2":"val2"}
    
    function2("arg1",
          *tupleCustomArgs,    #note *
          param3="arg3",
          param2="arg2", 
          **dictCustomNamedArgs     #note **
          )
    

    enfin la note * et ** dans les appels de fonction ci-dessus. Si nous omettons, nous pouvons obtenir de mauvais résultats.

    Omettant * dans tuple args:

    function2("arg1",
          tupleCustomArgs,   #omitting *
          param3="arg3",
          param2="arg2", 
          **dictCustomNamedArgs
          )
    

    imprime

    param1: arg1
    param2: arg2
    param3: arg3
    custom tuple params ----------
    ('custom param1', 'custom param2', 'custom param3'),
    custom named params ----------
    customNamedParam2:val2
    customNamedParam1:val1
    

    au-dessus de tuple ('custom param1', 'custom param2', 'custom param3') est imprimé tel quel.

    Omettant dict args:

    function2("arg1",
          *tupleCustomArgs,   
          param3="arg3",
          param2="arg2", 
          dictCustomNamedArgs   #omitting **
          )
    

    donne

    dictCustomNamedArgs
             ^
    SyntaxError: non-keyword arg after keyword arg
    
17
répondu Mahesha999 2017-11-27 07:03:04

en plus, vous pouvez également mélanger différents modes d'utilisation lors de l'appel de fonctions kwargs:

def test(**kwargs):
    print kwargs['a']
    print kwargs['b']
    print kwargs['c']


args = { 'b': 2, 'c': 3}

test( a=1, **args )

donne cette sortie:

1
2
3

notez que * * kwargs doit être le dernier argument

9
répondu philipp 2015-02-25 09:45:23

kwargs sont un sucre syntaxique pour passer des arguments de nom comme dictionnaires (pour func), ou dictionnaires comme arguments nommés(pour func)

5
répondu 2009-11-20 10:39:06

Voici une fonction simple qui sert à expliquer l'usage:

def print_wrap(arg1, *args, **kwargs):
    print(arg1)
    print(args)
    print(kwargs)
    print(arg1, *args, **kwargs)

tout argument qui est Non spécifié dans la définition de la fonction sera mis dans la liste args , ou la liste kwargs , selon qu'il s'agit d'arguments de mots clés ou non:

>>> print_wrap('one', 'two', 'three', end='blah', sep='--')
one
('two', 'three')
{'end': 'blah', 'sep': '--'}
one--two--threeblah

si vous ajoutez un argument de mot-clé qui n'est jamais passé à une fonction, une erreur sera soulevée:

>>> print_wrap('blah', dead_arg='anything')
TypeError: 'dead_arg' is an invalid keyword argument for this function
5
répondu naught101 2015-11-27 06:15:50

voici un exemple que j'espère utile:

#! /usr/bin/env python
#
def g( **kwargs) :
  print ( "In g ready to print kwargs" )
  print kwargs
  print ( "in g, calling f")
  f ( **kwargs )
  print ( "In g, after returning from f")

def f( **kwargs ) :
  print ( "in f, printing kwargs")
  print ( kwargs )
  print ( "In f, after printing kwargs")


g( a="red", b=5, c="Nassau")

g( q="purple", w="W", c="Charlie", d=[4, 3, 6] )

quand vous exécutez le programme, vous obtenez:

$ python kwargs_demo.py 
In g ready to print kwargs
{'a': 'red', 'c': 'Nassau', 'b': 5}
in g, calling f
in f, printing kwargs
{'a': 'red', 'c': 'Nassau', 'b': 5}
In f, after printing kwargs
In g, after returning from f
In g ready to print kwargs
{'q': 'purple', 'c': 'Charlie', 'd': [4, 3, 6], 'w': 'W'}
in g, calling f
in f, printing kwargs
{'q': 'purple', 'c': 'Charlie', 'd': [4, 3, 6], 'w': 'W'}
In f, after printing kwargs
In g, after returning from f

la clé emporte ici est que le nombre variable d'arguments nommés dans l'appel traduire dans un dictionnaire dans la fonction.

1
répondu user1928764 2016-05-26 21:37:28