Ü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?

Dave Hillier
quelle

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)
Dave Hillier
quelle
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}
David Parks
quelle
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.

llimllib
quelle
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)
Patrick Harrington
quelle
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