← Все вопросы

Почему опасно ставить список [] как значение аргумента по умолчанию?

Задан 6 месяцев назад1.5к просмотров4 ответа
25

Написал функцию def add(item, lst=[]):, которая должна добавлять элемент в список и возвращать его. Но при повторных вызовах список почему-то накапливает старые значения! В чём дело?

def add(item, lst=[]):
    lst.append(item)
    return lst

print(add(1))  # [1]
print(add(2))  # ожидаю [2], а получаю [1, 2]

4 ответа

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

Это знаменитая ловушка Python. Значение по умолчанию вычисляется ОДИН раз — в момент определения функции, а не при каждом вызове. То есть один и тот же объект-список переиспользуется между вызовами, поэтому он и накапливает элементы.

Правильный паттерн — ставить None, а список создавать внутри:

def add(item, lst=None):
    if lst is None:
        lst = []
    lst.append(item)
    return lst

print(add(1))  # [1]
print(add(2))  # [2]

Теперь при каждом вызове без аргумента создаётся новый список. То же касается словарей и множеств в качестве дефолта.

Дмитрий Экгауз а почему с числами и строками такой проблемы нет? — потому что они неизменяемы, их нельзя «дополнить» · 6 месяцев назад
Михаил Якимов боже, я неделю не мог понять этот баг 😄 · 6 месяцев назад
Иван Фролов лучшее объяснение, что встречал · 6 месяцев назад
13

Дефолт создаётся один раз при объявлении функции, а не каждый вызов. Используй None и проверку внутри.

5

Просто никогда не пиши =[] в аргументах, и всё.

-6

Это не баг, это фича, список же глобальный.

Елена Костюченко он не глобальный, он привязан к объекту функции — но всё равно общий между вызовами, формулировка неточная · 6 месяцев назад

Ваш ответ

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