Код: Выделить всё
adders = [None, None, None, None]
for i in [0, 1, 2, 3]:
adders[i] = lambda a: i+a
print adders[1](3)
Я ожидал 4. Я рассуждал так: в Python все является объектом, и поэтому каждая переменная является указателем на него. Создавая замыкания лямбда для i, я ожидал, что он сохранит указатель на целочисленный объект, на который в данный момент указывает i. Это означает, что когда я назначил новый целочисленный объект, это не должно влиять на ранее созданные замыкания. К сожалению, проверка массива adders в отладчике показывает, что это так. Все лямбда-функции ссылаются на последнее значение i, 3, в результате чего adders[1](3) возвращает 6.
Это заставляет меня задуматься о следующем:
- Что именно фиксируют замыкания?
- Какой самый элегантный способ убедить лямбда-функции фиксировать текущее значение i таким образом, что это не будет затронуто, когда i изменит свое значение?
Если вы пришли сюда, пытаясь решить проблему с созданием кнопок в Tkinter, попробуйте tkinter создать кнопки в аргументах команды цикла for, чтобы получить более конкретные советы.
Смотрите, что именно содержится в obj.__closure__? технические подробности о том, как Python реализует замыкания. См. В чем разница между ранним и поздним связыванием? для обсуждения соответствующей терминологии.