Мутабельный аргумент по умолчанию в Python

Мутабельный аргумент по умолчанию в Python

@python_quiz

Разберем этот квиз

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

Условие (код)

python

Что здесь происходит (интуиция и правило)

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

Демонстрация

python

Ожидаемый вывод (примерный):

Как видно, второй вызов добавляет ещё один элемент в тот же список, поэтому b становится [1, 1], а объекты a и b указывают на один и тот же список.

Разбор вариантов ответа

  • "Оба вызова вернут [1]" — не соответствует наблюдаемому поведению, поскольку второй вызов добавляет ещё один элемент.
  • "Первый — [1], второй — [1, 1]" — описывает именно поведение, возникающее при использовании мутабельного аргумента по умолчанию в данном коде.
  • "Первый — [], второй — [1]" — неверно: первый вызов добавляет 1 в дефолтный список, поэтому он не остаётся пустым.
  • "Оба вернут один и тот же объект [1, 1]" — неверно формулировано: после двух последовательных вызовов объект будет один и тот же, но первый вызов вернёт [1] в момент получения; после второго вызова значение этого же объекта изменится на [1, 1].

(Важный нюанс: если вы посмотрите на возвращаемую ссылку a после выполнения второго вызова, её содержимое тоже покажет [1, 1], потому что это тот же объект. Но в момент получения a сразу после первого вызова он был [1].)

Как избежать нежелательного поведения

Стандартный шаблон — использовать None как значение по умолчанию и создавать новый список внутри функции:

python

Проверка:

python

Теперь каждый вызов без аргумента получает новый список.

Когда такое поведение может быть полезно

Иногда хранение состояния между вызовами — желаемое поведение (например, кеширование, накапливание). Тогда использование мутабельного аргумента по умолчанию — компактный приём, но лучше документировать намерение явно или использовать замыкания/классы:

python

Или класс с полем состояния.

Вывод

Мутабельные аргументы по умолчанию в Python не пересоздаются при каждом вызове функции — они вычисляются один раз при определении функции и затем повторно используются. Это часто приводит к сюрпризам (как в приведённом примере), поэтому безопаснее применять паттерн с None или явно документировать и использовать накопительное поведение.

Report Page