2013-05-26 3 views
2

У меня есть массив функций, например:лямбда-функции и список функций в Python

>>> def f(): 
...  print "f" 
... 
>>> def g(): 
...  print "g" 
... 
>>> c=[f,g] 

Тогда я пытаюсь создать два лямбда-функции:

>>> i=0 
>>> x=lambda: c[i]() 
>>> i+=1 
>>> y=lambda: c[i]() 

И потом, их называют:

>>> x() 
g 
>>> y() 
g 

Почему c [i] в ​​лямбда одинаковы?

+0

_easy_ способ решить эту проблему - просто не создавать бесполезные «лямбды» в первую очередь. Просто замените эти две строки на 'x = c [i]' и 'y = c [i]', и вы получите именно те функции, которые вы хотели. Единственная причина когда-либо писать 'lambda: f()' вместо 'f' - это вставить' f' в пространство имен замыкания, чтобы посмотреть его позже, вместо того, чтобы просто использовать его. Вы не хотите делать это здесь, и на самом деле это именно то, что вызывает вашу проблему. – abarnert

ответ

10

Это потому, что функция лямбда выборки значение глобальной переменной i во время выполнения:

>>> i = 0 
>>> x=lambda z = i : c[z]() #assign the current value of `i` to a local variable inside lambda 
>>> i+=1 
>>> y =lambda z = i : c[z]() 
>>> x() 
f 
>>> y() 
g 

Необходимо прочитать: What do (lambda) function closures capture?

+0

Примечание: принятый ответ для связанного вопроса показывает, как сделать желаемое захват имен (см. Функцию createAdder в конце http://stackoverflow.com/a/2295368/25050. –

3

В закрытий Python не улавливают фактические значения, но вместо они захватывают пространства имен. Поэтому, когда вы используете i внутри своей функции, она фактически просматривается в охватывающей области. И ценность там уже изменилась.

Вам не нужны все эти lambda s и списки, чтобы увидеть это.

>>> x = 1 
>>> def f(): 
... print(x) 
... 
>>> x = 2 
>>> def g(): 
... print(x) 
... 
>>> g() 
2 
>>> f() 
2