Ответ
Проблема в том, что объект, используемый в качестве значения по умолчанию, создаётся только один раз — в момент определения функции, а не при каждом её вызове.
Если этот объект является изменяемым (например, list
или dict
), то все вызовы функции, которые не передают свой собственный аргумент, будут работать с одним и тем же экземпляром объекта, что приводит к неожиданным побочным эффектам.
Неправильный подход (демонстрация проблемы):
def add_item(item, items_list=[]):
items_list.append(item)
return items_list
# Первый вызов, всё выглядит нормально
list1 = add_item("apple")
print(list1) # Вывод: ['apple']
# Второй вызов изменяет тот же самый список
list2 = add_item("banana")
print(list2) # Неожиданный вывод: ['apple', 'banana']
Правильный подход (идиома с None
):
Для безопасной работы следует использовать None
в качестве значения по умолчанию и создавать новый изменяемый объект внутри функции.
def add_item(item, items_list=None):
# Если список не передан, создаём новый
if items_list is None:
items_list = []
items_list.append(item)
return items_list
# Первый вызов
list1 = add_item("apple")
print(list1) # Вывод: ['apple']
# Второй вызов работает с новым, независимым списком
list2 = add_item("banana")
print(list2) # Ожидаемый вывод: ['banana']