Почему изменяется аргумент по умолчанию при каждом вызове функции?
Сделал функцию с аргументом по умолчанию def add(x, lst=[]), и при повторных вызовах список не пустой — в нём остаются старые значения! Почему mutable default ведёт себя странно и как правильно?
1 ответ
Это знаменитая ловушка Python: значение по умолчанию вычисляется один раз — при определении функции, а не при каждом вызове. Если в умолчании стоит изменяемый объект (список, словарь, множество), то это один и тот же объект для всех вызовов, и он накапливает изменения.
Ошибка:
def add(x, lst=[]):
lst.append(x)
return lst
print(add(1)) # [1]
print(add(2)) # [1, 2] — а ожидали [2]!
print(add(3)) # [1, 2, 3]
Список [] создаётся единожды, поэтому между вызовами в нём остаются прежние элементы.
Правильный способ — ставить в умолчание None, а сам объект создавать внутри функции:
def add(x, lst=None):
if lst is None:
lst = []
lst.append(x)
return lst
print(add(1)) # [1]
print(add(2)) # [2] — теперь верно
Это же касается словарей (d={}) и множеств. Запомните правило: никогда не используйте изменяемые объекты как значения по умолчанию. Для них всегда пишите =None и инициализируйте внутри тела функции. С неизменяемыми значениями (числа, строки, кортежи) проблемы нет — их менять нельзя.