Изменяемый аргумент по умолчанию в Python
@python_quizРазберем этот квиз
Короткий пример:

Что выведет этот код?

Почему так происходит
- Значение аргумента по умолчанию вычисляется один раз — в момент определения функции, а не при каждом вызове.
- В данном случае default-значение lst — одна и та же изменяемая lista, хранящаяся между вызовами.
- Первый вызов добавляет 1 в этот список -> [1]. Второй вызов добавляет 2 в тот же список -> [1, 2].
Разбор вариантов ответов
- "Напечатает [1] и [2]": неверно, потому что для второго вызова используется тот же список, поэтому результат не сбрасывается.
- "Напечатает [1] и [1, 2]": соответствует тому, что действительно происходит — список накапливает элементы между вызовами.
- "Напечатает [1] и [1]": неверно — это было бы правдой, если бы для каждого вызова создавался новый список по умолчанию, но здесь он общий.
- "Выбросит исключение": неверно — код корректен и исключений не вызывает.
Как избежать побочного эффекта (правильный паттерн)
Если нужно, чтобы при каждом вызове создавался новый список, используйте None как значение по умолчанию и создавайте список внутри функции:

Ожидаемый вывод этого варианта:

Дополнительные советы
- Для неизменяемых значений (int, str, tuple) поведение аргументов по умолчанию обычно безопасно.
- Для изменяемых объектов (list, dict, set, пользовательские объекты) стоит явно задавать None и инициализировать внутри функции, если требуется новая коллекция при каждом вызове.
- Если вы намеренно хотите сохранить состояние между вызовами (например, в кэшах или накопителях), использование изменяемого default может быть удобным, но делайте это явно и документируйте поведение.
Вывод
Поведение аргумента по умолчанию в Python может привести к неожиданным последствиям при использовании изменяемых объектов. В большинстве случаев рекомендуют использовать None и инициализировать значение внутри функции, чтобы избежать нежелательной совместной мутации между вызовами.