passer l'argument ** kwargs à une autre fonction avec ** kwargs


152

Je ne comprends pas l'exemple suivant, disons que j'ai ces fonctions:

# python likes
def save(filename, data, **kwargs):
    fo = openX(filename, "w", **kwargs) # <- #1
    fo.write(data)
    fo.close()
# python doesnt like
def save2(filename, data, **kwargs):
    fo = openX(filename, "w", kwargs) # <- #2
    fo.write(data)
    fo.close()

def openX(filename, mode, **kwargs):
    #doing something fancy and returning a file object

Pourquoi la n ° 1 est-elle la bonne solution et la n ° 2 la mauvaise? **kwargsest fondamentalement un dict, donc si je veux transmettre l'argument à openX, je pense que la bonne façon serait de ne pas **donner le dict. Mais python n'aime évidemment pas le second et me dit que j'ai donné 3 arguments au lieu de 2. Alors, quelle est la raison derrière cela?

python 

5
Je me demande pourquoi vous l'appelez **argsdans le code. C'est peut-être le pire nom possible, car les gens le confondront avec*args
John La Rooy

1
Bon je n'utilise jamais vraiment * args, donc j'utilise ** args ^^, mais bon je peux le modifier.

Réponses:


155

Dans le deuxième exemple, vous fournissez 3 arguments: nom de fichier, mode et un dictionnaire ( kwargs). Mais Python attend: 2 arguments formels plus des arguments de mots-clés.

En préfixant le dictionnaire par «**», vous décompressez le dictionnaire kwargsen arguments de mots-clés.

Un dictionnaire (type dict) est une variable unique contenant des paires clé-valeur.

Les "arguments de mots clés" sont des paramètres de méthode clé-valeur.

Tout dictionnaire peut être décompressé en arguments de mot-clé en le préfixant **lors de l'appel de fonction.


5
Maintenant je comprends. Je pensais que les mots-clés et dict étaient la même chose.

13
"Tout dictionnaire peut être étendu aux mots-clés en le préfixant avec ** lors de l'appel de fonction." <- thats cool

1
Voir aussi: Documentation Python sur les paramètres de mots-clés et le déballage des listes d'arguments
dinosaure

8
Un exemple de code réel rendrait cette réponse beaucoup plus claire.
OrangeDog

13

La **syntaxe indique à Python de collecter les arguments de mot-clé dans un dictionnaire. Le le save2transmet comme un argument non-mot-clé (un objet de dictionnaire). Le openXne voit aucun argument de mot-clé donc le **argsn'est pas utilisé. Il obtient plutôt un troisième argument non-mot-clé (le dictionnaire). Pour résoudre ce problème, modifiez la définition de la openXfonction.

def openX(filename, mode, kwargs):
    pass

Merci, mais je veux aussi utiliser openX sans enregistrer, donc je dois m'en tenir aux mots-clés. Je pensais que passer des mots-clés était fondamentalement la même chose que transmettre un dict, mais je ne savais pas jusqu'à présent :)

@xMRW Cela ne peut pas être la même chose puisque vous pouvez également passer un dictionnaire comme paramètre à n'importe quelle fonction. Votre n ° 1 est alors le bon.
Keith

8

En développant la réponse de @gecco, voici un exemple qui vous montrera la différence:

def foo(**kwargs):
    for entry in kwargs.items():
        print("Key: {}, value: {}".format(entry[0], entry[1]))

# call using normal keys:
foo(a=1, b=2, c=3)
# call using an unpacked dictionary:
foo(**{"a": 1, "b":2, "c":3})

# call using a dictionary fails because the function will think you are
# giving it a positional argument
foo({"a": 1, "b": 2, "c": 3})
# this yields the same error as any other positional argument
foo(3)
foo("string")

Ici vous pouvez voir comment déballer un dictionnaire et pourquoi l'envoi d'un dictionnaire échoue


1

Parce qu'un dictionnaire est une valeur unique. Vous devez utiliser l'expansion des mots clés si vous souhaitez le transmettre sous forme de groupe d'arguments de mots clés.


désolé mais qu'est-ce qu'une "expansion de mots clés"? voulez-vous dire que je devrais utiliser dict_var au lieu de ** args et juste utiliser def func (argument, dict_var = 0) ... func (1, {1: "a", 2: "b"})

1

Pour # 2, les arguments seront uniquement un paramètre formel avec une valeur dict, mais pas un paramètre de type mot-clé.

Si vous souhaitez passer un paramètre de type de mot-clé dans un argument de mot-clé, vous devez spécifier ** avant votre dictionnaire, ce qui signifie ** args

Consultez ceci pour plus de détails sur l'utilisation de ** kw

http://www.saltycrane.com/blog/2008/01/how-to-use-args-and-kwargs-in-python/


Il y a donc une grande différence entre ** kwargs et dict?

merci, j'aime toujours en savoir plus sur des sujets que je ne comprends pas.
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.