2010-08-07 20 views
39

Bir döngü içinde işlevler oluşturmaya ve bunları bir sözlükte depolamaya çalışıyorum. Sorun, sözlükteki tüm girişlerin son oluşturulan işlevle eşleşmesiyle sonuçlanmasıdır. Kod şöyledir:Döngüde işlevler oluşturma

d = {} 
def test(**kwargs): 
    for k in kwargs: 
     def f(): 
      print k, kwargs[k] 
     d[k] = f 
     f() 

test(foo=1, bar=2) 
print 'should print the same output as before' 
d['foo']() 
d['bar']() 

Bu çıkışlar: neden

foo 1 
bar 2 
should print the same output as before 
bar 2 
bar 2 

fikrin var mı?

+1

: http://docs.python-guide.org/en/latest/writing/gotchas/#late-binding-closures –

cevap

82

Sen geç bağlayıcı bir sorun haline koşuyoruz - Her fonksiyon mümkün olduğunca geç k arar (test dışında çağrıldığında dolayısıyla bu döngü sona ermesinden sonra gerçekleşir).

Kolayca erken bağlama zorlayarak sabit: Değişikliği def f():def f(k=k): için - varsayılan değerleri baktı edilmektedir (sağ elini kk=k yılında k=k sol tarafta bulunan k olduğu argümanı adı k, için varsayılan değerdir) zamanında değil, def zaman, bu yüzden özellikle erken bağlama için bir yol arıyoruz.

def make_f(kwargs, k): 
    def f(): 
     print k, kwargs[k] 
    return f 

ve: Eğer f fazladan argüman alma (ve dolayısıyla potansiyel olarak hatalı çağrıldığını) endişeleniyorsan

, bir "fonksiyonu fabrika" olarak bir kapak yardımıyla ilgili daha sofistike bir yolu var senin döngü def ifade yerine f = make_f(kwargs, k) kullanın. Kendime bir hatırlatma olarak