Я пытаюсь создать функции внутри цикла:
functions = []
for i in range(3):
def f():
return i
# alternatively: f = lambda: i
functions.append(f)
Проблема в том, что все функции в конечном итоге одинаковы. Вместо того, чтобы возвращать 0, 1 и 2, все три функции возвращают 2:
print([f() for f in functions])
# expected output: [0, 1, 2]
# actual output: [2, 2, 2]
Почему это происходит и что мне делать, чтобы получить 3 разные функции, которые выводят 0, 1 и 2 соответственно?
У вас проблема с поздним связыванием - каждая функция ищет i
как можно позже (таким образом, при вызове после окончания цикла, i
будет установлено на 2
) .
Легко исправить путем принудительного раннего связывания: измените def f ():
на def f (i = i):
вот так:
def f(i=i):
return i
Значения по умолчанию (справа i
в i = i
- значение по умолчанию для имени аргумента i
, которое является левым i
в i. = i
) ищутся во время def
, а не во время вызова
, так что по сути это способ специально искать раннее связывание.
Если вас беспокоит, что f
получит дополнительный аргумент (и, следовательно, потенциально может быть вызван ошибочно), есть более изощренный способ, предполагающий использование замыкания в качестве «фабрики функций»:
def make_f(i):
def f():
return i
return f
и в вашем цикле используйте f = make_f (i)
вместо оператора def
.