Изменяемый аргумент по умолчанию
Проблема
1 2 3 4 5 6 7
Ожидалось, что каждый вызов начнёт с пустого списка. На деле список один на все вызовы: функция «накапливает» данные между запусками.
Почему так происходит
Значение по умолчанию вычисляется один раз — в момент определения функции, а не при каждом вызове. Список создался единожды, и все вызовы работают с ним же.
Для неизменяемых значений (0, None, строка, кортеж) проблемы нет: их нельзя изменить, поэтому «накопления» не возникает. Опасны только изменяемые объекты — список, словарь, множество.
| Значение по умолчанию | Безопасно? |
|---|---|
| def f(x, n=0) | да |
| def f(x, s="") | да |
| def f(x, t=()) | да |
| def f(x, a=[]) | нет |
| def f(x, d={}) | нет |
Как правильно:
1 2 3 4 5 6 7 8
Шаблон один и тот же: по умолчанию ставим None, а внутри создаём объект заново.
Тот же эффект в словарях
1 2 3 4 5 6
А вот так — можно
Если аргумент по умолчанию не изменяется внутри функции, проблемы нет:
1 2
Но полагаться на это рискованно: стоит потом добавить extra.append(...), и ошибка вернётся. Проще всегда писать None.
