Короткий ответ
Код выведет [1], а затем [1, 2]. Причина — изменяемый список как значение аргумента по умолчанию: такой объект создаётся один раз и разделяется между всеми вызовами функции.
Как это работает подробнее
Значения аргументов по умолчанию вычисляются в момент определения функции, а не при каждом вызове.
- Единственный экземпляр. Когда Python выполняет строку с
def, список[]создаётся один раз, и ссылка на него сохраняется как значение по умолчанию. - Разделение между вызовами. Первый вызов добавляет в общий список 1, второй обращается к тому же объекту и добавляет 2 — получается
[1, 2]. - Накопление состояния. Такой список ведёт себя как глобальное состояние, сохраняя значения между вызовами, — это классический источник трудноуловимых багов.
- Другие изменяемые типы. Та же проблема возникает со словарями и множествами, поэтому их тоже избегают в значениях по умолчанию.
Пример кода
Опасный и идиоматичный вариант
def add_item(item, some_list=[]):
some_list.append(item)
return some_list
print(add_item(1)) # [1]
print(add_item(2)) # [1, 2] — список общий для всех вызовов
def add_item(item, some_list=None):
if some_list is None:
some_list = []
some_list.append(item)
return some_list
print(add_item(1)) # [1]
print(add_item(2)) # [2] — каждый раз новый списокЧто использовать на практике
- None как маркер. Используй
Noneв значении по умолчанию и создавай новый список внутри функции — это идиоматический паттерн Python. - Проверка на None. Сравнение делай через
is None, чтобы понять, передан ли аргумент явно.