Почему в Python следующий код ведёт себя неожиданно? Объясните результат и предложите исправления.
def add_item(x, lst=[]):
lst.append(x)
return lst
print(add_item(1))
print(add_item(2))

12 Окт в 08:20
8 +8
0
Ответы
1

Проблема в том, что значение аргумента по умолчанию вычисляется один раз — в момент определения функции. В вашем примере lst = создаётся одна и та же список-объект и затем переиспользуется при каждом вызове функции без явной передачи lst. Поэтому последовательные вызовы модифицируют один и тот же список.

Что у вас происходит:

Первый вызов add_item111 даёт 111.Второй вызов add_item222 добавляет 2 в уже существующий список -> 1,21, 21,2.

Иллюстрация можнопосмотретьidспискаможно посмотреть id спискаможнопосмотретьidсписка:

def add_itemx,lst=[]x, lst=[]x,lst=[]:
print′id(lst)=′,id(lst)'id(lst) =', id(lst)id(lst)=,id(lst) lst.appendxxx return lst
printadditem(1)add_item(1)addi tem(1) # id одинаковый
printadditem(2)add_item(2)addi tem(2)

Как исправить
1) Использовать "sentinel" None рекомендуемыйподходрекомендуемый подходрекомендуемыйподход:

def add_itemx,lst=Nonex, lst=Nonex,lst=None:
if lst is None:
lst = lst.appendxxx return lst
printadditem(1)add_item(1)addi tem(1) # 111 printadditem(2)add_item(2)addi tem(2) # 222

2) Всегда передавать новый список при вызове:

printadditem(1,[])add_item(1, [])addi tem(1,[]) printadditem(2,[])add_item(2, [])addi tem(2,[])

3) Если нужно принять уже существующий список, но не изменять переданный объект — делать копию:

def add_itemx,lst=Nonex, lst=Nonex,lst=None:
if lst is None:
lst = else:
lst = listlstlstlst # копия
lst.appendxxx return lst

Это не баг Python, а ожидаемое поведение. Для мутабельных объектов list,dict,setит.п.list, dict, set и т.п.list,dict,setит.п. по умолчанию лучше использовать None и создавать объект внутри функции.

12 Окт в 09:38
Не можешь разобраться в этой теме?
Обратись за помощью к экспертам
Гарантированные бесплатные доработки в течение 1 года
Быстрое выполнение от 2 часов
Проверка работы на плагиат
Поможем написать учебную работу
Прямой эфир