Ответ
Проблема в том, что объект, используемый в качестве значения по умолчанию, создаётся только один раз — в момент определения функции, а не при каждом её вызове.
Если этот объект является изменяемым (например, list или dict), то все вызовы функции, которые не передают свой собственный аргумент, будут работать с одним и тем же экземпляром объекта, что приводит к неожиданным побочным эффектам.
Неправильный подход (демонстрация проблемы):
def add_item(item, items_list=[]):
items_list.append(item)
return items_list
# Первый вызов, всё выглядит нормально
list1 = add_item("apple")
print(list1) # Вывод: ['apple']
# Второй вызов изменяет тот же самый список
list2 = add_item("banana")
print(list2) # Неожиданный вывод: ['apple', 'banana']
Правильный подход (идиома с None):
Для безопасной работы следует использовать None в качестве значения по умолчанию и создавать новый изменяемый объект внутри функции.
def add_item(item, items_list=None):
# Если список не передан, создаём новый
if items_list is None:
items_list = []
items_list.append(item)
return items_list
# Первый вызов
list1 = add_item("apple")
print(list1) # Вывод: ['apple']
# Второй вызов работает с новым, независимым списком
list2 = add_item("banana")
print(list2) # Ожидаемый вывод: ['banana'] Ответ 18+ 🔞
А, слушай, вот это классика, блядь! Прямо как Герасим с Муму, только в коде. Сейчас объясню, а то сам от себя охуеешь, когда поймёшь.
Смотри, ты пишешь функцию, типа, "добавь мне, сука, элемент в список". И думаешь: "А, пусть по умолчанию пустой список будет, удобно же!". И пишешь вот такую пиздопроебибну:
def add_item(item, items_list=[]):
items_list.append(item)
return items_list
И вроде бы всё логично, да? Ага, щас! Вот ты вызываешь её первый раз:
list1 = add_item("apple")
print(list1) # Вывод: ['apple']
Всё, сука, окей! Работает! Ты довольный, как слон, думаешь: "Я гений, ёпта!". А потом вызываешь второй раз:
list2 = add_item("banana")
print(list2) # Неожиданный вывод: ['apple', 'banana']
И тут тебя накрывает, блядь, медным тазом! Ты такой: "Чё за хуйня? Я же новый список хотел!". А он тебе: "Получай, мудила, старый, с яблоком!".
А вся соль в том, что этот самый [] — он создаётся один раз и навсегда, в момент, когда Питон читает твою функцию. Не при каждом вызове, нет! Он как тот самый Герасимов мешок — один на всех. И все, кто не принёс свой список, лезут в этот общий, и там всё перемешивается, блядь! Овердохуища неожиданностей!
Так что делать-то, спросишь? А делать надо по-взрослому, с подвохом! Используй None, эту хитрожопую заглушку.
Правильный подход, чтобы не облажаться:
def add_item(item, items_list=None):
# Если список не передан, создаём новый
if items_list is None:
items_list = []
items_list.append(item)
return items_list
Вот теперь работает как часы, ебать мои старые костыли! Каждый раз, когда ты не передаёшь список, функция внутри создаёт свежий, новенький, девственный список. И никаких общих яблок с бананами!
# Первый вызов
list1 = add_item("apple")
print(list1) # Вывод: ['apple']
# Второй вызов работает с новым, независимым списком
list2 = add_item("banana")
print(list2) # Ожидаемый вывод: ['banana']
Вот и вся магия, Колян. Запомни: изменяемые объекты в аргументах по умолчанию — это путь в никуда, в рот меня чих-пых! Всегда используй None и создавай внутри. И будет тебе счастье, а не сюрприз в виде общего мудацкого списка на всех.