Übergeben eines Wörterbuchs an eine Funktion als Schlüsselwortparameter


345

Ich möchte eine Funktion in Python mit einem Wörterbuch aufrufen.

Hier ist ein Code:

d = dict(param='test')

def f(param):
    print(param)

f(d)

Dies wird gedruckt, {'param': 'test'}aber ich möchte, dass es nur gedruckt wird test.

Ich möchte, dass es für weitere Parameter ähnlich funktioniert:

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

Ist das möglich?

Antworten:


528

Ich habe es am Ende selbst herausgefunden. Es ist einfach, ich habe nur den Operator ** vermisst, um das Wörterbuch zu entpacken

So wird mein Beispiel:

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

57
Wenn Sie möchten, dass dies anderen hilft, sollten Sie Ihre Frage umformulieren: Das Problem bestand nicht darin, ein Wörterbuch zu übergeben. Sie wollten, dass ein Diktat in Schlüsselwortparameter umgewandelt wird
Javier

11
Es ist erwähnenswert, dass Sie Listen auch in Positionsargumente entpacken können: f2 (* [1,2])
Matthew Trevor

10
"Dereferenzierung": Der übliche Begriff in diesem Python-Kontext ist "entpacken". :)
Mipadi

2
Dies ist großartig. Verwenden Sie es einfach mit argparse / __ dict__, um es wirklich einfach zu machen, Befehlszeilenargumente direkt in Optionen für ein Klassenobjekt zu analysieren.
Horus

1
Was ist der Grund, warum wir ein Wörterbuch entpacken möchten, wenn wir es als Argument an eine Funktion übergeben?
Mona Jalal

128
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

Ein paar zusätzliche Details, die hilfreich sein könnten (Fragen, die ich nach dem Lesen hatte und getestet habe):

  1. Die Funktion kann Parameter haben, die nicht sind im Wörterbuch enthalten sind
  2. Das kannst du nicht einen Parameter, der bereits im Wörterbuch enthalten überschreiben
  3. Das Wörterbuch kann keine Parameter enthalten, die nicht in der Funktion enthalten sind.

Beispiele:

Nummer 1: Die Funktion kann Parameter haben, die nicht im Wörterbuch enthalten sind

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

Nummer 2: Sie können einen Parameter, der bereits im Wörterbuch enthalten ist, nicht überschreiben

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

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

Nummer 3: Das Wörterbuch kann keine Parameter enthalten, die nicht in der Funktion enthalten sind.

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

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

Wie in den Kommentaren gefordert, eine Lösung für Nummer 3 darin, das Wörterbuch anhand der in der Funktion verfügbaren Schlüsselwortargumente zu filtern:

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

Eine andere Möglichkeit besteht darin, zusätzliche kwargs in Ihrer Funktion zu akzeptieren (und zu ignorieren):

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

Beachten Sie, dass Sie Positionsargumente und Listen oder Tupel genauso wie kwargs verwenden können. Hier ist ein erweitertes Beispiel, das sowohl Positions- als auch Schlüsselwortargumente enthält:

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}

4
Das Entpacken mit print.format ist besonders nützlich. zB:'hello {greeting} {name}'.format( **{'name': 'Andrew', 'greeting': 'Mr'})
Martlark

Alte Frage, aber immer noch sehr relevant. Danke für die ausführliche Antwort. Kennen Sie Möglichkeiten, um Fall 3 zu umgehen? Bedeutet dies, dass die Elemente des Wörterbuchs pythonisch den Funktionsparametern zugeordnet werden, wenn das Wörterbuch mehr Elemente enthält als Parameter?
Spencer

2
@spencer Der Antwort wurde eine Lösung hinzugefügt.
David Parks

33

In Python wird dies als "Auspacken" bezeichnet, und Sie können etwas darüber im Tutorial finden . Die Dokumentation ist zum Kotzen, da stimme ich zu, vor allem, weil es so fantastisch nützlich ist.


20
Es ist besser, den relevanten Inhalt des Links in Ihre Antwort zu kopieren, als sich darauf zu verlassen, dass der Link bis zum Ende der Zeit überlebt.
Richard

3
@Richard, das ist eine tiefe philosophische Meinung über das Web, der ich nicht herzlicher widersprechen könnte! Leider fehlt mir der Platz in diesem Rand, um meinen wunderbaren Beweis zu teilen ...
llimllib

@llimllib, dann muss ich Dr. Wiles fragen!
Richard

6

Los geht's - funktioniert wie jedes andere iterable:

d = {'param' : 'test'}

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

f(d)

Es scheint, dass die Leute dies ablehnen, da es die ursprüngliche Frage beantwortet, nicht die umformulierte Frage. Ich schlage vor, diesen Beitrag jetzt einfach zu entfernen.
Dotancohen

@dotancohen nein, es war nie korrekt, es schlägt der zweite Codeblock fehl, der immer mit der Frage war. Es nahm es zu wörtlich, der Druck war ein Beispiel.
Dave Hillier

Es beantwortet die Frage jedoch nicht über das Auspacken des Wörterbuchs. Sein Ansatz ist aufgrund der gestellten Frage vollkommen gültig.
Natecat
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.