Шаг 123.
Python: сборник рецептов.
Функции. Захват переменных в анонимных функциях

    На этом шаге мы рассмотрим особенности реализации этой операции.

Задача

    Вы определили анонимную функцию, используя lambda, но вы также хотите захватить значения некоторых переменных во время определения.

Решение

    Рассмотрим поведение следующей программы:

>>> x = 10
>>> a = lambda y: x + y
>>> x = 20
>>> b = lambda y: x + y
>>> 

    А теперь задайте себе вопрос: какими будут значения a(10) и b(10)? Если вы думаете, что 20 и 30, то ошибаетесь:

>>> a(10)
30
>>> b(10)
30
>>>

    Проблема в том, что значение х, используемое в lambda-выражении, является свободной переменной, которая связывается во время выполнения, а не во время определения. Так что значение х в lambda-выражениях будет таким, каким ему случится быть во время выполнения. Например:

>>> x = 15 
>>> a(10)
25
>>> x = 3 
>>> a(10)
13
>>>

    Если же вы хотите, чтобы анонимная функция захватывала значение во время определения и сохраняла его, используйте значение по умолчанию:

>>> x = 10
>>> a = lambda y, x=x: x + y
>>> x = 20
>>> b = lambda y, x=x: x + y
>>> a(10)
20
>>> b(10)
30
>>> 


Обсуждение

    Проблема, которую мы рассматриваем в этом рецепте, возникает, когда случается перемудрить с lambda-функциями. Например, вы можете ожидать, что при создании списка lambda-выражений с использованием генератора списка или цикла lambda-функции запомнят итерационные переменные во время определения. Например:

>>> funcs = [lambda x: x + n for n in range(5)]
>>> for f in funcs:
	print(f(0))

	
4
4
4
4
4
>>>

    Обратите внимание, что все функции считают, что n имеет последнее значение, полученное в ходе итераций. Теперь сравните со следующим:

>>> funcs = [lambda x, n=n: x + n for n in range(5)]
>>> for f in funcs:
	print(f(0))

	
0
1
2
3
4
>>> 

    Как вы видите, теперь функции захватывают значения n во время определения.

    На следующем шаге мы рассмотрим, как заставить вызываемый объект с N аргументами работать так же, как вызываемый объект с меньшим количеством аргументов.




Предыдущий шаг Содержание Следующий шаг