Мутабельные аргументы по умолчанию в Python
@python_quizРазберем этот квиз
Кратко о проблеме: короткий фрагмент кода на Python демонстрирует неожиданные результаты при использовании изменяемого объекта (списка) в качестве значения аргумента по умолчанию. Разберёмся, почему так происходит и как этого избежать.
Исходный код

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

Анализ возможных вариантов вывода
Рассмотрим типичные варианты, которые могут прийти в голову:
- Выводы по одному элементу в каждой строке, но с разными значениями:
- [1] и затем [2] — нет, второй вызов не создаёт новый список, он использует тот же.
- [1] и затем [1] — нет, второй вызов добавляет новый элемент в список, поэтому результат изменится.
- Ошибка времени выполнения — нет, код корректен и ошибок не вызывает.
- Накопление элементов: [1] и затем [1, 2] — это именно то, что и происходит, потому что список по умолчанию сохраняется между вызовами.
Как избежать сюрпризов
Рекомендуемый паттерн — использовать None как значение по умолчанию и создавать новый список внутри функции:

Теперь каждый вызов без аргумента lst получает новый список.
Альтернативный вариант — явно передавать новый список при каждом вызове, когда это уместно:

(Здесь используется предыдущая безопасная реализация с lst=None.)
Выводы и рекомендации
- Не используйте изменяемые объекты (списки, словари, множества) непосредственно в качестве значений аргументов по умолчанию, если вы ожидаете, что при каждом вызове будет создаваться новый объект.
- Используйте None и создавайте новый объект внутри функции, или явно передавайте объект при вызове.
- Понимание того, что значения по умолчанию вычисляются один раз при определении функции, помогает избежать трудноуловимых багов в практике.