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

8 Янв в 06:50
17 +1
0
Ответы
1
Проблема: при последовательных вызовах без аргумента `lst` все вызовы используют одну и ту же список-значение по умолчанию, поэтому элементы накапливаются.
Почему так происходит (коротко и технически):
- Значение параметров по умолчанию вычисляется один раз — в момент определения функции, а не при каждом вызове. В результате для `def add_item(item, lst=[])` создаётся один объект списка и сохраняется в `function.__defaults__`.
- При каждом вызове без явного `lst` функция получает ссылку на этот один и тот же список (те же id), и `append` модифицирует его.
Пример нежелательного поведения:
```
def add_item(item, lst=[]):
lst.append(item)
return lst
print(add_item(1)) # [1]
print(add_item(2)) # [1, 2] <-- ожидают [2], но список общий
```
Как исправить (рекомендуемый вариант — sentinel None):
```
def add_item(item, lst=None):
if lst is None:
lst = []
lst.append(item)
return lst
```
Теперь:
```
print(add_item(1)) # [1]
print(add_item(2)) # [2]
```
Альтернативы:
- Всегда передавать новый список при вызове: `add_item(1, [])`.
- Использовать неизменяемое значение по умолчанию (например, `None`/`()`), или фабрику для создания нового объекта внутри функции.
- В редких случаях, если нужно кэширование между вызовами, можно намеренно использовать мутируемый default, но это следует документировать явно.
8 Янв в 06:58
Не можешь разобраться в этой теме?
Обратись за помощью к экспертам
Гарантированные бесплатные доработки в течение 1 года
Быстрое выполнение от 2 часов
Проверка работы на плагиат
Поможем написать учебную работу
Прямой эфир