Bir işlevi anahtar sözcük parametresi olarak bir işleve iletme


346

Sözlük kullanarak python'da bir fonksiyon çağırmak istiyorum.

İşte bazı kod:

d = dict(param='test')

def f(param):
    print(param)

f(d)

Bu yazdırılıyor {'param': 'test'}ama sadece yazdırmasını istiyorum test.

Daha fazla parametre için benzer şekilde çalışmasını istiyorum:

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

Mümkün mü?

Yanıtlar:


529

Sonunda kendim için anladım. Basit, sadece ** operatörü sözlüğü açmak için kaçırıyordum

Yani benim örneğim:

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

57
bunun başkalarına yardım etmesini istiyorsanız, sorunuzu yeniden ifade etmelisiniz: sorun bir sözlükten geçmiyordu, istediğiniz bir dikteyi anahtar kelime parametrelerine dönüştürmekti
Javier

11
Listeleri konumsal bağımsız değişkenlere de açabileceğinizi belirtmek gerekir: f2 (* [1,2])
Matthew Trevor

10
"dereference": bu Python bağlamında olağan terim "paketten çıkarma" dır. :)
mipadi

2
Bu harika, sadece bir sınıf nesnesi için seçeneklere doğrudan komut satırı argümanı ayrıştırma işlemini kolaylaştırmak için argparse / __ dict__ ile birlikte kullanıldı.
Horus

1
sözlüğü bir işleve argüman olarak iletirken paketini açmak istememizin nedeni nedir?
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

Bilmenizde yardımcı olabilecek birkaç ek ayrıntı (bunu okuduktan ve test ettikten sonra aldığım sorular):

  1. Fonksiyon parametreleri olabilir değil sözlüğe dahil
  2. Sen olabilir değil sözlükte zaten bir parametre geçersiz
  3. Sözlük olabilir değil işlevde olmayan parametreleri var.

Örnekler:

Sayı 1: İşlev sözlükte bulunmayan parametrelere sahip olabilir

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

Sayı 2: Sözlükte zaten olan bir parametreyi geçersiz kılamazsınız

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

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

Sayı 3: Sözlük işlevde olmayan parametreler içeremez.

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

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

Yorumlarda istendiği gibi, Sayı 3 için bir çözüm , sözlüğü işlevde bulunan anahtar kelime bağımsız değişkenlerine göre filtrelemektir:

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

Başka bir seçenek, işlevinizdeki ek kwargları kabul etmek (ve yoksaymak):

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

Konumsal bağımsız değişkenleri ve listeleri veya tuples'ları kwargs ile aynı şekilde kullanabileceğinizden daha fazla dikkat edin, işte hem konumsal hem de anahtar kelime argümanlarını içeren daha gelişmiş bir örnek:

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
Print.format ile ambalajı açmak özellikle yararlıdır. örneğin:'hello {greeting} {name}'.format( **{'name': 'Andrew', 'greeting': 'Mr'})
Martlark

Eski soru ama yine de çok alakalı. Detaylı cevap için teşekkürler. Vaka 3'ün üzerinde çalışmanın yollarını biliyor musunuz? Anlamı sözlükte, parametrelerden daha fazla öğe olduğunda, sözlük öğelerini işlev parametrelerine eşleştirin.
spencer

2
@spencer cevaba bir çözüm eklendi.
David Parks

33

Piton, bu "açma" denir ve bu konuda biraz bulabilirsiniz öğretici . Dokümantasyonu berbat, katılıyorum, özellikle de fanatik olarak ne kadar yararlı olduğu için.


20
Bağlantının ilgili içeriğini, zamanın sonuna kadar hayatta kalan bağlantıya güvenmek yerine cevabınıza kopyalamak daha iyidir.
Richard

3
@Richard, web hakkında derinden felsefi bir görüş, bu da daha yürekten katılmıyorum! Ne yazık ki, harika kanıtımı paylaşmak için bu kenar boşluğundaki alandan yoksun ...
llimllib

@llimllib, Dr. Wiles'a sormam gerekecek!
Richard

6

Buyrun - diğer tüm yinelenebilir çalışır:

d = {'param' : 'test'}

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

f(d)

Anlaşılan soruya değil, orijinal soruyu cevapladığı için insanlar bunu küçümsüyor gibi görünüyor. Bu yazıyı şimdi kaldırmanızı öneririm.
dotancohen

@dotancohen hayır asla doğru olmadı, her zaman soruyla ilgili ikinci kod bloğunu başarısız olur. Kelimenin tam anlamıyla aldı, baskı bir örnek oldu.
Dave Hillier

Ancak soruyu cevaplıyor, sadece sözlük açma yoluyla yapmıyor. Yaklaştığı soruya göre yaklaşımı mükemmel bir şekilde geçerlidir.
Natecat
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.