← Все вопросы

Почему изменяется аргумент по умолчанию при каждом вызове функции?

Задан 16 месяцев назад508 просмотров1 ответ
9

Сделал функцию с аргументом по умолчанию def add(x, lst=[]), и при повторных вызовах список не пустой — в нём остаются старые значения! Почему mutable default ведёт себя странно и как правильно?

1 ответ

14
✓ Принятый ответ — помог автору

Это знаменитая ловушка 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 и инициализируйте внутри тела функции. С неизменяемыми значениями (числа, строки, кортежи) проблемы нет — их менять нельзя.

Ваш ответ

Войдите, чтобы ответить на вопрос.