В обоих примерах поиск происходит во время выполнения. Единственное отличие состоит в том, что есть локально определенная переменная x
, в то время как нет локально определенной переменной y
.
При выполнении ...
def foo(x):
def bar():
print y
return bar
y = 5
bar = foo(2)
bar()
... оператор print
ищет переменную с именем y
и находит ее только в глобальном контексте, поэтому использует ее и печатает "5".
В ...
def foo(x):
def bar():
print x
return bar
x = 5
bar = foo(2)
bar()
... когда происходит поиск, является определяемой переменной x
, которая фиксируется на "5" при вызове функции foo
.
Ключ в том, что аргументы оцениваются в момент их передачи в функции, поэтому внешняя функция foo
оценивает аргументы, переданные при вызове. Это фактически создает переменную с именем x
в контексте функции foo
, поэтому всякий раз, когда выполняется bar
, она видит эту переменную, а не глобально определенную.
Иногда это может сбивать с толку, как в следующем коде:
lst = []
for i in range(5):
x = i
lst.append(lambda: x)
for func in lst:
print func() # prints 4 4 4 4 4
Вам нужно сделать:
lst = []
for i in range(5):
def _func(x):
return lambda: x
lst.append(_func(i))
for func in lst:
print func() # prints 0 1 2 3 4