Лямбды Python и обзор

Учитывая этот отрывок кода:

funcs = []
for x in range(3):
    funcs.append(lambda: x)
print [f() for f in funcs]

Я ожидал бы, что это распечатает [0, 1, 2], но вместо этого это печатает [2, 2, 2]. Действительно ли там что-то фундаментально, я отсутствую о том, как лямбды работают с объемом?

7
задан p-static 17 December 2009 в 20:14
поделиться

3 ответа

Это частый вопрос в Python. В основном область видимости такова, что при вызове f () она будет использовать текущее значение x , а не значение x в то время, когда лямбда сформирован. Существует стандартный обходной путь:

funcs = []
for x in range(10):
funcs.append(lambda x=x: x)
print [f() for f in funcs]

Использование лямбда x = x извлекает и сохраняет текущее значение x .

8
ответ дан 6 December 2019 в 11:49
поделиться

x привязан к уровню модуля x (который остался после цикла for).

Немного яснее:

funcs = []

for x in range(10):
    funcs.append(lambda: x)

x = 'Foo'

print [f() for f in funcs]

# Prints ['Foo', 'Foo', 'Foo', 'Foo', 'Foo', 'Foo', 'Foo', 'Foo', 'Foo', 'Foo']
5
ответ дан 6 December 2019 в 11:49
поделиться

Вы знаете ответ: да. ;) Однако успокойтесь, так как это очень частое открытие для начинающих питонистов. Когда вы определяете функцию или лямбду, которая ссылается на переменные, не «созданные» внутри этой функции, она создает замыкание для переменных. В результате вы получаете значение переменной при вызове функции, а не значение во время определения. (Вы ожидали последнего.)

Есть несколько способов справиться с этим. Первый - это привязка дополнительных переменных:

funcs = []
for x in range(10):
    funcs.append(lambda x=x: x)
print [f() for f in funcs]
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Второй способ немного более формальный:

from functools import partial
funcs = []
for x in range(10):
    funcs.append(partial(lambda x: x, x))
print [f() for f in funcs]
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
4
ответ дан 6 December 2019 в 11:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: