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

Почему нельзя использовать изменяемый объект как значение аргумента по умолчанию?

JuniorФункции
Ещё спрашивают так:
  • Что не так с def f(x=[])?
  • Почему список в аргументе по умолчанию накапливает значения?
Коротко

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

  • Изменяемый объект ([], {}) тогда общий для всех вызовов и копит изменения
  • Правильно: def f(items=None) и внутри if items is None: items = []

А ещё Иногда этим пользуются намеренно — как простым кэшем, но это лучше явно оформить

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

Подробно

Когда Python выполняет строку def, он создаёт объект функции и в этот же момент вычисляет значения по умолчанию. Они сохраняются в атрибуте __defaults__ и переиспользуются при каждом вызове, где аргумент не передан.

Для неизменяемых значений (0, None, строка) это незаметно. Но если по умолчанию стоит список или словарь и функция его меняет, изменения остаются в том же объекте и видны в следующих вызовах.

Стандартное решение — сентинел None: в сигнатуре None, а новый список создаётся внутри функции при каждом вызове. Если None — допустимое значение аргумента, используют собственный сентинел: _missing = object().

Та же логика касается любых выражений по умолчанию: def log(t=time.time()) запомнит время определения функции, а не вызова.

Пример

def add(item, items=[]):
    items.append(item)
    return items

add(1)   # [1]
add(2)   # [1, 2] — тот же список!

def add(item, items=None):
    if items is None:
        items = []
    items.append(item)
    return items

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

  • Причина: значение вычисляется один раз при def.
  • Решение через None и создание объекта внутри.
  • Понимание, что проблема только при изменении объекта.

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

  • Объяснять «Python так кэширует списки» без указания момента вычисления.
  • Решение items = items or []: оно подменит и переданный пустой список, что может быть неожиданно для вызывающего.

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

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

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

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

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

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