2012-01-20 43 views
18

Sadece Eric Lippert'in Closing over the loop variable considered harmful'u SO üzerinden koştum ve deneyden sonra Python'da aynı problemin var olduğunu (ve hatta daha da zorlaştığını) fark ettim.Bir döngü değişkenini kapatmak için Pythonic bir yolu var mı?

>>> l = [] 
>>> for r in range(10): 
... def foo(): 
...  return r 
... l.append(foo) 
... 
>>> for f in l: 
... f() 
... 
9 
9 
9 
# etc 

ve standart C# geçici çözüm bu Python bir sorunla pek olmadığını fark

>>> l = [] 
>>> for r in range(10): 
... r2 = r 
... def foo(): 
...  return r2 
... l.append(foo) 
... 
>>> for f in l: 
... f() 
... 
9 
9 
9 
# etc 

(çünkü Python referansların doğanın varsayıyorum) çalışmıyor Kapanmayan nesne yapıları üzerine genel vurgu, ama ben bu işlemek için açık Pythonic bir yol varsa merak ediyorum ya da aslında yeni vars oluşturmak için iç içe işlev çağrıları JS yol gitmek zorunda mıyım?

>>> l = [] 
>>> for r in range(10): 
...  l.append((lambda x: lambda: x)(r)) 
... 
>>> for f in l: 
...  f() 
... 
0 
1 
2 
# etc 

cevap

23

bir yolu, varsayılan değeri ile bir parametre kullanmaktır:

l = [] 
for r in range(10): 
    def foo(r = r): 
     return r 
    l.append(foo) 

for f in l: 
    print(f()) 

bu foo 'nin yerel kapsamında bir r tanımlar için bu çalışır

0 
1 
2 
3 
4 
5 
6 
7 
8 
9 

verir ve bağlanan foo zamanında tanımlanmış olan varsayılan değer.


başka yolu da bir işlev fabrika kullanmaktır: o make_foo 'ın yerel kapsamında r tanımlar ve make_foo(r) çağrıldığında buna bir değer bağlar çünkü

l = [] 
for r in range(10): 
    def make_foo(r): 
     def foo(): 
      return r 
     return foo 
    l.append(make_foo(r)) 

for f in l: 
    print(f()) 

Bu çalışır. Daha sonra, f() çağrıldığında, , LEGB rule kullanılarak araştırılır. r, foo yerel kapsamında bulunmasa da, make_foo kapsayıcı kapsamında bulunur.

+1

Bu varsayılan argüman numarasını beğeniyorum. Bu işlev fabrikası, benimki sonunda çift lambda şeyine semantik olarak benziyor. Yine de Lambda fabrikaları okunabilirlik duygusu. – quodlibetor

İlgili konular