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

10 Дек 2025 в 08:21
31 +1
0
Ответы
1
Коротко: поведение неожиданно, потому что значение параметра по умолчанию вычисляется один раз при определении функции и потом переиспользуется — поэтому один и тот же изменяемый объект (список) накапливает значения между вызовами.
Пример (показательно):
def f(x=[]):
x.append(111)
return x
Вызовы:
f() -> [1][1][1] f() -> [1,1][1, 1][1,1] f() -> [1,1,1][1, 1, 1][1,1,1]
Исправление — использовать немутируемый маркер (обычно None) и создавать новый список внутри тела:
def f(x=None):
if x is None:
x = []
x.append(111)
return x
Теперь:
f() -> [1][1][1] f() -> [1][1][1] f() -> [1][1][1]
Когда допустимо использовать изменяемые значения по умолчанию:
- Когда вы намеренно хотите сохранять состояние между вызовами (например, кэш, аккумулятор). Тогда поведение — ожидаемое и полезное.
- Когда значение по умолчанию само по себе немутируемо (числа, строки, кортежи) — таких проблем нет.
Замечания: если вам нужен глобальный/разделяемый кэш, лучше сделать это явно (атрибут функции, класс, functools.lru_cache и т.д.), чтобы код был читабельнее и безопаснее (особенно в многопоточной среде).
10 Дек 2025 в 08:27
Не можешь разобраться в этой теме?
Обратись за помощью к экспертам
Гарантированные бесплатные доработки в течение 1 года
Быстрое выполнение от 2 часов
Проверка работы на плагиат
Поможем написать учебную работу
Прямой эфир