Python лямбды и обзор - PullRequest
       20

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

7 голосов
/ 17 декабря 2009

Учитывая этот фрагмент кода:

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

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

Ответы [ 3 ]

8 голосов
/ 17 декабря 2009

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

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

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

5 голосов
/ 17 декабря 2009

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']
4 голосов
/ 17 декабря 2009

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

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

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]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...