web-dev-qa-db-fra.com

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

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 le n ° 1 est-il la bonne solution et le n ° 2 le mauvais? **kwargs est fondamentalement un dict, donc si je veux passer l'argument à openX, je pense que la bonne façon serait sans ** et de simplement donner le dict. Mais python n'aime évidemment pas le second et me dit que j'ai donné 3 arguments au lieu de 2 arguments… .. Quelle est la raison derrière tout cela?

108
user945967

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 kwargs en 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 mot-clé en le préfixant par ** lors de l'appel de la fonction.

113
gecco

La syntaxe ** indique à Python de collecter les arguments de mots clés dans un dictionnaire. Le save2 le transmet en tant qu'argument non mot clé (un objet dictionnaire). La openX ne voit pas d'argument de mot clé, donc le **args n'est pas utilisé. Au lieu de cela, il s'agit d'un troisième argument non mot clé (le dictionnaire). Pour résoudre ce problème, changez la définition de la fonction openX.

def openX(filename, mode, kwargs):
    pass
9
Keith

Parce qu'un dictionnaire est une valeur unique. Vous devez utiliser le développement de mots clés si vous souhaitez le transmettre en tant que groupe d'arguments de mots clés.

1

Pour # 2 Args ne sera qu'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/

1
Kit Ho

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 fonctionne la décompression d'un dictionnaire et pourquoi l'envoi d'un dictionnaire réel échoue.

1
Reda Drissi

La déclaration à ce qui précède est:

modèle def (caractéristiques, cible):.

Cela fait partie du code où nous utilisons des approches de régularisation, L1 et L2, pour éventuellement réduire les surajustements. Je reçois le message d'erreur "pas de module nommé args" après avoir tapé "arguments globaux". 

0
Charles B