2012-01-20 17 views
18

Po prostu przebiegłem przez Eric'a Lippert'a Closing over the loop variable considered harmful przez SO, i po eksperymentach zdałem sobie sprawę, że ten sam problem istnieje (i jest jeszcze trudniejszy do obejścia) w Pythonie.Czy istnieje Pythoniczny sposób na zamknięcie zmiennej pętli?

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

, a średnia C# obejście nie działa (zakładam, ze względu na charakter odniesień w Pythonie)

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

uznaję, że to nie jest wielkim problemem w Pythonie z jego ogólny nacisk na niezamknięte struktury obiektów, ale jestem ciekawy, czy istnieje oczywisty sposób Pythonic do obsługi tego, czy też musimy iść na ścieżkę JS zagnieżdżonych wywołań funkcji, aby utworzyć faktycznie nowe vary?

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

Odpowiedz

23

Jednym ze sposobów jest użycie parametru z wartością domyślną:

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

for f in l: 
    print(f()) 

daje w wyniku

0 
1 
2 
3 
4 
5 
6 
7 
8 
9 

To działa, ponieważ definiuje r w zakresie lokalnym foo „s, i wiąże domyślna wartość to w chwili zdefiniowania foo.


Innym sposobem jest użycie fabrykę funkcję:

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()) 

To działa, ponieważ definiuje r w zakresie lokalnym make_foo „s, i wiąże się z nim, gdy wartość make_foo(r) nazywa. Później, gdy zostanie wywołana f(), zostanie wyszukana r przy użyciu LEGB rule. Chociaż r nie został znaleziony w lokalnym zasięgu foo, znajduje się w zakresie obejmującym make_foo.

+1

Och, podoba mi się ta domyślna sztuczka z argumentem. Ta fabryka funkcji jest semantycznie podobna do podwójnej rzeczy lambda na końcu mojej. Jednak fabryki Lambda są zmorą czytelności. – quodlibetor

Powiązane problemy