Получить доступ

Что такое замыкание?

JuniorФункции
Ещё спрашивают так:
  • Как работают замыкания в Python?
  • Зачем нужен nonlocal?
  • Почему лямбды в цикле возвращают одно и то же значение?
Коротко

Замыкание — вложенная функция, которая помнит переменные внешней функции после её завершения.

  • Захватывается сама переменная, а не значение на момент создания
  • Чтобы присвоить захваченной переменной, нужен nonlocal

А ещё Ловушка: лямбды в цикле видят последнее значение счётчика

Так подсказку видит пользователь sotto на живом собеседовании — за пару секунд, пока вы думаете вслух.

Подробно

Если внутренняя функция использует имя из объемлющей функции, Python сохраняет ссылку на эту переменную в «ячейке» (cell). Внешняя функция может завершиться, а внутренняя продолжит видеть и читать эту переменную. Ячейки видны в func.__closure__.

Зачем: фабрики функций (make_multiplier(3)), декораторы, колбэки с контекстом, простое хранение состояния без класса.

Присваивание. Если внутри вложенной функции присвоить имени значение, Python считает его локальным. Чтобы изменить захваченную переменную, её объявляют nonlocal (для глобальной — global).

Позднее связывание. Замыкание хранит переменную, а не её значение в момент создания. Классическая ловушка — функции, созданные в цикле: все они ссылаются на одну переменную цикла и видят её последнее значение. Решения — аргумент по умолчанию (lambda i=i: i) или functools.partial.

Пример

def counter():
    count = 0
    def inc():
        nonlocal count
        count += 1
        return count
    return inc

c = counter()
c(), c()                      # (1, 2)

funcs = [lambda: i for i in range(3)]
[f() for f in funcs]          # [2, 2, 2] — позднее связывание

funcs = [lambda i=i: i for i in range(3)]
[f() for f in funcs]          # [0, 1, 2]

Что хотят услышать

  • Определение: вложенная функция + захват переменных объемлющей области.
  • Где применяется: декораторы, фабрики функций.
  • nonlocal для изменения захваченной переменной.
  • Позднее связывание и способ его обойти.

Частые ошибки

  • «Замыкание копирует значение переменной» — хранится ссылка на переменную.
  • Получить UnboundLocalError из-за присваивания без nonlocal.

Что спросят дальше

Связанные вопросы

Закрытая бета

Подсказки на собеседовании — в реальном времени

sotto слышит вопрос интервьюера и показывает короткий ответ и план, как в блоке «Коротко». Оставьте контакт — пришлём доступ и промокод.

  • Промокод на 2 часа — сверх пробных 30 минут
  • Программа для Windows — скачать сразу, войти — через Яндекс ID или VK ID
  • Прямая связь с разработчиком: что улучшить — сделаем