Дан фрагмент на Python: def foo(a=[]): a.append(1); return a; — объясните поведение при множественных вызовах, чем отличаются изменяемые и неизменяемые параметры, и как сделать функцию безопасной для многократного использования

26 Апр в 20:38
22 +1
0
Ответы
1
Кратко — почему так происходит, отличие изменяемых/неизменяемых и как исправить.
1) Поведение данного фрагмента
- Параметр по умолчанию `a=[]` вычисляется один раз при определении функции и используется в каждом последующем вызове, поэтому все вызовы работают с одним и тем же списком. Пример:
- первый вызов `foo()` вернёт [1] [1] [1];
- второй вызов `foo()` вернёт [1,1] [1, 1] [1,1];
- и т.д.
2) Изменяемые vs неизменяемые параметры
- Изменяемые (list, dict, set, большинство объектов) можно изменять "на месте" (методы вроде `append`, `update` и т.п.), поэтому изменение внутри функции сохраняется между вызовами.
- Неизменяемые (int, str, tuple, frozenset и т.п.) нельзя изменить на месте — операции создают новые объекты, поэтому дефолтные значения не «накопливают» изменения (например, `x=0` останется 000 при каждом новом вызове, если вы делаете `x += 1` внутри функции, это создаст новый объект).
3) Как сделать функцию безопасной
- Используйте `None` (или другой неизменяемый «маркер») как значение по умолчанию и создавайте новый объект внутри функции:
def foo(a=None):
if a is None:
a = []
a.append(1)
return a
Теперь:
- `foo()` вернёт [1] [1] [1];
- второй `foo()` снова вернёт [1] [1] [1] — список не накапливает значения между вызовами.
Дополнительно:
- Можно принимать очевидно создаваемый объект и при необходимости копировать входной аргумент (`a = list(a)`), если хотите избежать изменения внешнего списка.
- Для полей в dataclass используйте `default_factory`.
26 Апр в 20:44
Не можешь разобраться в этой теме?
Обратись за помощью к экспертам
Гарантированные бесплатные доработки в течение 1 года
Быстрое выполнение от 2 часов
Проверка работы на плагиат
Поможем написать учебную работу
Прямой эфир