Задать вопрос

Не могу понять кое-что про замыкание. Можете помочь?

Читаю 4-е издание "Изучаем Python" М. Лутца. На 492-й странице говорится такое правило:
если lambda-выражение или инструкция def вложены в цикл внутри другой
функции и вложенная функция ссылается на переменную из объемлющей об-
ласти видимости, которая изменяется в цикле, все функции, созданные в этом
цикле, будут иметь одно и то же значение – значение, которое имела перемен-
ная на последней итерации.

и дается такой пример:
def makeActions():
    acts = []
        for i in range(5):                                       # Сохранить каждое значение i
            acts.append(lambda x: i ** x)                # Все запомнят последнее значение i!
    return acts

acts = makeActions()

Потом показывается что:
acts[0](2), acts[2](2) и acts[4](2) возвращают 4 ** 2, т. е. 16.
Проверил все это, работает точно так, как говорит автор. Но вот вопрос: почему последнее значение цикла for, как это реализуется в питоне
  • Вопрос задан
  • 1189 просмотров
Подписаться 4 Оценить Комментировать
Решения вопроса 2
vittly
@vittly
Оптимизатор, любитель удалять лишний код
В массиве acts лежат по-сути одинаковые лямбды - каждая захватила себе в замыкание переменную i и возвращает ее удвоенное значение. Последним значением i было 4. Соответственно любая из лямбд возвращает 16. На переменную надо смотреть как на область памяти, для переменной i - это одна и таже область, из какой бы лямбды вы к ней не обращались
Ответ написан
bobrovskyserg
@bobrovskyserg
Более разумно вопрос звучит так: почему последнее значение i?
Потому что это - переменная замыкания, и она хранится в специальном месте, одном на всех:
print(acts[0].__closure__)
print(acts[1].__closure__)
print(acts[0].__closure__[0].cell_contents)


Изменить ситуацию можно, например, так:
def makeActions():
    acts = []
    for i in range(5):
        def f(x, a=i):
            return a ** x
        acts.append(f)
    return acts

или даже так (сам не знал, что с лямбдами работает)
acts.append(lambda x, a=i: a ** x)
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
@steel_dog
Спасибо за коментарии.
А может кто описать по подробнее каждую строку в действии на словах.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

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