Разберите код на Python с использованием аргумента по умолчанию def f(a, lst=[]): lst.append(a); return lst — объясните распространённую ошибку, почему список накапливается между вызовами, и предложите варианты исправления

11 Ноя в 09:34
3 +1
0
Ответы
1
Проблема. В Python значение параметра по умолчанию вычисляется один раз — при определении функции. Если это изменяемый объект (например, список), то все вызовы функции без явного аргумента будут использовать один и тот же объект, поэтому он накапливает данные.
Пример исходного кода:
def f(a, lst=[]):
lst.append(a)
return lst
Поведение при вызовах:
f(1) -> [1] [1] [1]
f(2) -> [1,2] [1, 2] [1,2] (ожидаем [2] [2] [2], но 리스트 накопился)
Исправления (варианты).
1) Использовать sentinel None (рекомендуемый способ):
def f(a, lst=None):
if lst is None:
lst = []
lst.append(a)
return lst
Теперь:
f(1) -> [1] [1] [1]
f(2) -> [2] [2] [2]
2) Возвращать новый список (не менять переданный):
def f(a, lst=()):
return list(lst) + [a]
(здесь по умолчанию кортеж — неизменяемый — и каждый вызов возвращает новый список)
3) Копировать входной список внутри функции (если нужно сохранить исходный аргумент):
def f(a, lst=None):
if lst is None:
lst = []
else:
lst = list(lst) # или lst.copy()
lst.append(a)
return lst
4) Явно использовать фабрику (реже нужно):
_sentinel = object()
def f(a, lst=_sentinel):
if lst is _sentinel:
lst = []
lst.append(a)
return lst
Замечание: исходное поведение не баг интерпретатора — полезно, если вы намеренно хотите разделяемое состояние между вызовами. Если этого не нужно, применяйте один из указанных паттернов (обычно вариант с None).
11 Ноя в 10:19
Не можешь разобраться в этой теме?
Обратись за помощью к экспертам
Гарантированные бесплатные доработки в течение 1 года
Быстрое выполнение от 2 часов
Проверка работы на плагиат
Поможем написать учебную работу
Прямой эфир