web-dev-qa-db-fra.com

Passer un dictionnaire à une fonction en tant que paramètres de mot clé

J'aimerais appeler une fonction dans python à l'aide d'un dictionnaire.

Voici du code:

d = dict(param='test')

def f(param):
    print(param)

f(d)

Ceci imprime {'param': 'test'} mais je voudrais qu'il imprime simplement test.

J'aimerais que cela fonctionne de la même manière pour plus de paramètres:

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

Est-ce possible?

307
Dave Hillier

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

Donc, mon exemple devient:

d = dict(p1=1, p2=2)
def f2(p1,p2):
    print p1, p2
f2(**d)
473
Dave Hillier
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 qu'il serait peut-être utile de connaître (questions que j'avais après avoir lu ceci et que je suis allé tester):

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

Exemples:

Nombre 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

Nombre 2: Vous ne pouvez pas remplacer un paramètre déjà présent 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 paramètres 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'

Comme demandé dans les commentaires, une solution à Number 3 consiste à filtrer le dictionnaire en fonction des arguments de mots clés disponibles dans la fonction:

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

Une autre option consiste à accepter (et à ignorer) les kwargs supplémentaires dans votre fonction:

In[15]: def myfunc2(a=None, **kwargs):
In[16]:    print(a)

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

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

Notez bien que vous pouvez utiliser des arguments de position, des listes ou des tuples de la même manière que kwargs. Voici un exemple plus avancé incorporant tout ce qui précède:

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}
95
David Parks

En python, cela s'appelle "décompresser", et vous en trouverez un peu dans le tutorial . La documentation sur ça craint, je suis d'accord, surtout à cause de son utilité fantastique.

30
llimllib

Voilà, ça marche - ça marche n'importe quel autre itérable:

d = {'param' : 'test'}

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

f(d)
6
Patrick Harrington