2011-09-22 23 views
6

Kod görüşmeler:lambda işlevi Python'daki parametreyi kapatmıyor mu? daha


from pprint import pprint 

li = [] 

for i in range(5): 
     li.append(lambda : pprint(i)) 

for k in li: 
     k() 

verim:

 
4 
4 
4 
4 
4 

neden olmasın

 
0 
1 
2 
3 
4 

??

Teşekkürler.

P.S. Ben tam bir dekoratör yazarsanız, beklendiği gibi çalışır: Sadece yerine Düzgün i başvuru yok i

+0

[bu soru] bölümüne bakın (http://stackoverflow.com/q/2295290/195823) ve [bu soruya cevabım] (http://stackoverflow.com/questions/2295290/what-do-lambda- işlev kapanışları-yakalama-python/2295372 # 2295372) –

+0

Özgün döngüyü bir işleve taşıyarak değişkeni kapatmakta olduğunu görüyoruz ve sonra işlevini "k in li" satırından önce çağırıyorsunuz. Bu modül düzeyinde kapsamda geçerli bir isim değil. Hala çalışmaya devam edecektir (ve aynı sonucu elde ettiğinden, değeri değil referansı kapatır), yani ismin kapalı olduğu anlamına gelir. – agf

+0

Hepinize teşekkür ederim.Bence http://stackoverflow.com/questions/2295290/what-do-lambda-function-closures-capture-in-python/2295368#2295368 sadece çözümü değil aynı zamanda neden olduğunu da söyler. Sanırım sorum http://stackoverflow.com/questions/2295290/what-do-lambda-function-closures-capture-in-python – Grissiom

cevap

10

yapmanız gereken şey şu ki, listeniz dolduğunda, i, yineleme sona erdiğinde sıradaki son öğe olarak atanan değere sahip olacaktı, bu yüzden her şeyden önce 410'u gördünüz.

3

mevcut değerini yakalamak için

lambda i=i: pprint(i) 

:



from pprint import pprint 

li = [] 

#for i in range(5): 
     #li.append(lambda : pprint(i)) 

def closure(i): 
     def _func(): 
       pprint(i) 
     return _func 

for i in range(5): 
     li.append(closure(i)) 

for k in li: 
     k() 
0

Lambda işlevleri i değişkeninin üzerinde kapanmalar oluşturur. İlk for döngü bittiğinde, i, 4 değerine sahiptir.

Daha sonra ikinci for döngü başlar ve tüm lambda işlevleri gerçekleştirilir. Bunların her biri 4 olan i'un geçerli değerini yazdırır. - yanlışlıkla bağımsız değişkenle adlandırılan eğer hata tanıtmak olabilir - Varsayılan bir argüman kullanmak istemiyorsanız

3

Eğer iç içe geçmiş bir lambda kullanabilirsiniz: Bu bir anonim versiyonu

from pprint import pprint 

li = [] 

for i in range(5): 
    li.append((lambda x: lambda: pprint(x))(i)) 

for k in li: 
    k() 

senin closure işlevi.

0

Yanıt: lambda içindeki kod i genel değişkeninizi kullandığından.

parametreyi i kaldırırsanız Kişisel ikinci varyant lambda'da ilki ile aynı yapacağız:

def closure(): 

yerine

def closure(i): 

yani İşlev içindeki kod i genel değişkenini kullanır.

+0

ile çoğaltılır. Değişkenin kapsamıyla ilgisi yoktur, aslında kapalı olan, bir değerden ziyade bir değere referanstır. Soruya verdiğim yorumu gör - eğer 'menzil için i' döngüsünü bir işleve taşıyorsanız, bu yüzden 'global kapsamda yok, daha sonra' li için döngüden önce işlevi çağırın. aynı cevabı verecektir. – agf

+0

> Eğer aralık i'nin içindeki i looplevini bir i intolev içine hareket ettirirseniz, o zaman global kapsamda bulunmam, then olur, sonra li döngüde k before beforen before calln i calllevini arar, aynı cevabı verir ... --- ie yerel olmayan? Demek istediğim şey o. – warvariuc

+0

'i' değişkenini arıyor. işlev argümanı olmadığı için 'i' dış kapsamdan 'i' değişkeni alır. – warvariuc

İlgili konular