Дан код на Python: def append_to_list(x, lst=[]): lst.append(x); return lst. Объясните поведение при последовательных вызовах, почему возникает «ловушка», и предложите корректные альтернативы

18 Мая в 03:53
12 +1
0
Ответы
1
Поведение и причина «ловушки»
Даная функция
def append_to_list(x, lst=[]):
lst.append(x)
return lst
по умолчанию создает список один раз при определении функции, а не при каждом вызове. Поэтому при последовательных вызовах без явного второго аргумента используется один и тот же список, и элементы накапливаются:
print(append_to_list(111)) # => [1][1][1]
print(append_to_list(222)) # => [1,2][1, 2][1,2]
print(append_to_list(333, lst=[])) # => [3][3][3] (при передаче нового списка поведение обычное)
Итого: «ловушка» в том, что дефолтный mutable-объект (список, словарь и т.п.) создаётся один раз и затем разделяется между вызовами.
Корректные альтернативы
1) Использовать None и создавать новый список внутри:
def append_to_list(x, lst=None):
if lst is None:
lst = []
lst.append(x)
return lst
2) Использовать уникальный sentinel:
_sentinel = object()
def append_to_list(x, lst=_sentinel):
if lst is _sentinel:
lst = []
lst.append(x)
return lst
3) Возвращать новый список (не мутировать входной):
def append_to_list(x, lst=None):
return (lst or []) + [x]
Примечания
- То же касается любых изменяемых типов (dict, set, пользовательские объекты).
- Если нужен именно постоянный накапливающийся список между вызовами — делайте это явно (глобальная переменная или параметр класса) и документируйте.
18 Мая в 03:59
Не можешь разобраться в этой теме?
Обратись за помощью к экспертам
Гарантированные бесплатные доработки в течение 1 года
Быстрое выполнение от 2 часов
Проверка работы на плагиат
Поможем написать учебную работу
Прямой эфир