Для функции на Python `def add_item(x, lst=[]): lst.append(x); return lst` объясните, почему поведение может показаться неожиданным, и предложите корректные варианты реализации с объяснением причин

1 Июн в 10:39
10 +1
0
Ответы
1
Проблема: значение дефолтного аргумента вычисляется один раз при определении функции, поэтому один и тот же список используется при всех вызовах. Из‑за этого последовательные вызовы накапливают элементы в одном списке. Пример неожиданного поведения:
Код (ваша функция)
def add_item(x, lst=[]):
lst.append(x)
return lst
Вызовы:
add_item(1) -> [1][1][1]
add_item(2) -> [1,2][1, 2][1,2] (ожидаем [2][2][2], но список общий)
Корректные варианты
1) Стандартный (рекомендуемый) — использовать `None` и создавать новый список внутри:
def add_item(x, lst=None):
if lst is None:
lst = []
lst.append(x)
return lst
Пояснение: дефолт `None` неизменяем и не разделяется между вызовами; новый список создаётся при каждом вызове, если аргумент не передан.
2) Функциональный (не меняет переданный список, возвращает новый список):
def add_item(x, lst=None):
if lst is None:
lst = []
return lst + [x]
Пояснение: возвращается новый список (операция `+` создаёт копию), полезно когда не хотите мутировать входной `lst`.
3) Использовать уникальный sentinel, если `None` может быть законным значением:
_sentinel = object()
def add_item(x, lst=_sentinel):
if lst is _sentinel:
lst = []
lst.append(x)
return lst
Пояснение: применимо если `None` — допустимый аргумент и нужно различать "не передан" и "передан None".
Короткая сводка: не используйте изменяемые объекты (например [][][]) как дефолтные значения; вместо этого создавайте их внутри тела функции (через `None` или sentinel) или возвращайте новую коллекцию.
1 Июн в 10:45
Не можешь разобраться в этой теме?
Обратись за помощью к экспертам
Гарантированные бесплатные доработки в течение 1 года
Быстрое выполнение от 2 часов
Проверка работы на плагиат
Поможем написать учебную работу
Прямой эфир