Проанализируйте следующий Python-код и объясните вывод, указав на особенности замыканий: `funcs = [lambda x=i: x for i in range(3)]; print([f() for f in funcs])`
Вывод: [0,1,2][0, 1, 2][0,1,2]. Объяснение коротко: - Цикл `for i in range(3)` присваивает iii значения (0,1,2)(0, 1, 2)(0,1,2). - В выражении `lambda x=i: x` параметр `x` — дефолтный аргумент; его значение вычисляется в момент определения лямбды и фиксируется. Поэтому каждая лямбда получает своё сохранённое значение iii на момент создания. - При вызове `[f() for f in funcs]` каждая функция возвращает своё зафиксированное значение, давая [0,1,2][0, 1, 2][0,1,2]. Контраст (частая ошибка): - Если бы писали `lambda: i` (без `x=i`), все лямбды замкнули бы на одну переменную iii по ссылке, и после завершения цикла iii равен 222, так что результат был бы [2,2,2][2, 2, 2][2,2,2].
Объяснение коротко:
- Цикл `for i in range(3)` присваивает iii значения (0,1,2)(0, 1, 2)(0,1,2).
- В выражении `lambda x=i: x` параметр `x` — дефолтный аргумент; его значение вычисляется в момент определения лямбды и фиксируется. Поэтому каждая лямбда получает своё сохранённое значение iii на момент создания.
- При вызове `[f() for f in funcs]` каждая функция возвращает своё зафиксированное значение, давая [0,1,2][0, 1, 2][0,1,2].
Контраст (частая ошибка):
- Если бы писали `lambda: i` (без `x=i`), все лямбды замкнули бы на одну переменную iii по ссылке, и после завершения цикла iii равен 222, так что результат был бы [2,2,2][2, 2, 2][2,2,2].