475 votes

Transférer un dictionnaire à une fonction en tant que paramètres de mots-clés

Je voudrais appeler une fonction en python en utilisant un dictionnaire avec des paires clé-valeur correspondantes pour les paramètres.

Voici un peu de code:

d = dict(param='test')

def f(param):
    print(param)

f(d)

Cela imprime {'param': 'test'} mais je voudrais juste imprimer test.

Je voudrais que cela fonctionne de manière similaire pour plusieurs paramètres:

d = dict(p1=1, p2=2)
def f2(p1, p2):
    print(p1, p2)
f2(d)

Est-ce possible?

0 votes

@JoonhoPark pourquoi ne pas écrire une question indépendante pour celle de votre commentaire?

711voto

Dave Hillier Points 4391

J'ai fini par comprendre par moi-même à la fin. C'est simple, il me manquait juste l'opérateur ** pour déballer le dictionnaire

Donc mon exemple devient :

d = dict(p1=1, p2=2)
def f2(p1,p2):
    print(p1, p2)
f2(**d)

90 votes

Si vous voulez que cela aide les autres, vous devriez reformuler votre question : le problème n'était pas de passer un dictionnaire, ce que vous vouliez était de convertir un dict en paramètres de mot-clé

17 votes

Il est à noter que vous pouvez également déballer des listes en arguments positionnels : f2 (*[1,2])

12 votes

"déréférence" : le terme habituel, dans ce contexte Python, est "déballer". :)

215voto

David Parks Points 12896
In[1]: def myfunc(a=1, b=2):
In[2]:    print(a, b)

In[3]: mydict = {'a': 100, 'b': 200}

In[4]: myfunc(**mydict)
100 200

Quelques détails supplémentaires qui pourraient être utiles à savoir (questions que je me posais après la lecture de ceci et que j'ai testées):

  1. La fonction peut avoir des paramètres qui ne sont pas inclus dans le dictionnaire
  2. Vous ne pouvez pas remplacer un paramètre de fonction qui est déjà dans le dictionnaire
  3. Le dictionnaire ne peut pas avoir de valeurs qui ne sont pas dans la fonction.

Exemples:

Numéro 1: La fonction peut avoir des paramètres qui ne sont pas inclus dans le dictionnaire

In[5]: mydict = {'a': 100}
In[6]: myfunc(**mydict)
100 2

Numéro 2: Vous ne pouvez pas remplacer un paramètre de fonction qui est déjà dans le dictionnaire

In[7]: mydict = {'a': 100, 'b': 200}
In[8]: myfunc(a=3, **mydict)

TypeError: myfunc() got multiple values for keyword argument 'a'

Numéro 3: Le dictionnaire ne peut pas avoir de valeurs qui ne sont pas dans la fonction.

In[9]:  mydict = {'a': 100, 'b': 200, 'c': 300}
In[10]: myfunc(**mydict)

TypeError: myfunc() got an unexpected keyword argument 'c'

Comment utiliser un dictionnaire avec plus de clés que d'arguments de fonction:

Une solution au point #3, ci-dessus, est d'accepter (et d'ignorer) des kwargs supplémentaires dans votre fonction (notez qu'en convention, _ est un nom de variable utilisé pour quelque chose qui est jeté, même si techniquement c'est juste un nom de variable valide pour Python):

In[11]: def myfunc2(a=None, **_):
In[12]:    print(a)

In[13]: mydict = {'a': 100, 'b': 200, 'c': 300}

In[14]: myfunc2(**mydict)
100

Une autre option est de filtrer le dictionnaire en fonction des arguments de mot-clé disponibles dans la fonction:

In[15]: import inspect
In[16]: mydict = {'a': 100, 'b': 200, 'c': 300}
In[17]: filtered_mydict = {k: v for k, v in mydict.items() if k in [p.name for p in inspect.signature(myfunc).parameters.values()]}
In[18]: myfunc(**filtered_mydict)
100 200

Exemple avec des arguments positionnels et des arguments de mot-clé:

Remarquez également que vous pouvez utiliser des arguments positionnels et des listes ou des tuples de manière efficace de la même manière que les kwargs, voici un exemple plus avancé combinant à la fois des arguments positionnels et des arguments de mots-clés:

In[19]: def myfunc3(a, *posargs, b=2, **kwargs):
In[20]:    print(a, b)
In[21]:    print(posargs)
In[22]:    print(kwargs)

In[23]: mylist = [10, 20, 30]
In[24]: mydict = {'b': 200, 'c': 300}

In[25]: myfunc3(*mylist, **mydict)
10 200
(20, 30)
{'c': 300}

6 votes

En utilisant le déballage avec print.format est particulièrement utile. par exemple: 'hello {greeting} {name}'.format( **{'name': 'Andrew', 'greeting': 'M.'})

0 votes

Ancienne question mais toujours très pertinente. Merci pour la réponse détaillée. Savez-vous s'il existe des moyens de contourner le cas 3? C'est-à-dire faire correspondre de manière pythonique les éléments du dictionnaire aux paramètres de la fonction, lorsque le dictionnaire contient plus d'éléments que de paramètres?

3 votes

@spencer une solution a été ajoutée à la réponse.

36voto

llimllib Points 1494

En python, cela s'appelle "déballage", et vous pouvez trouver un peu d'informations à ce sujet dans le tutoriel. La documentation sur ce sujet est mauvaise, je suis d'accord, surtout en raison de son utilité fantastique.

34 votes

Il est préférable de copier le contenu pertinent du lien dans votre réponse, plutôt que de compter sur le lien pour survivre jusqu'à la fin des temps.

5 votes

@Richard c'est une opinion philosophique profonde sur le web, avec laquelle je ne pourrais pas être plus en désaccord! Hélas, je n'ai pas assez de place dans cette marge ici pour partager ma merveilleuse preuve...

1 votes

@llimllib, je devrai donc demander à Dr. Wiles!

6voto

Patrick Harrington Points 7836

Voici - fonctionne comme n'importe quel autre iterable :

d = {'param' : 'test'}

def f(dictionnaire):
    for key in dictionnaire:
        print key

f(d)

0 votes

Il semble que les gens votent négativement pour cela car cela répond à la question originale, pas à la question reformulée. Je suggère simplement de supprimer ce message maintenant.

0 votes

@dotancohen non, ce n'était jamais correct, il échoue sur le deuxième bloc de code qui était toujours avec la question. Il a pris cela trop littéralement, l'impression était un exemple.

1 votes

Cela répond cependant à la question, mais pas via le dépaquetage de dictionnaire. Son approche est parfaitement valable en fonction de la question posée.

-2voto

Aleksandr P. Points 1

Veuillez trouver une brève explication dans le prochain tutoriel : http://docs.python.org/2.7/tutorial/controlflow.html#unpacking-argument-lists

" * fonctionne pour les listes et ** pour les dictionnaires "

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