В Питон, аргументы по умолчани вычислятся только один раз — в момент определэния функции, а не при каждом ё вызове. Это значи, что если в качестве значэни по умолчани для параметра используетси изменяемый объект (как список или словарь), он будет общим для всех вызовов функции, где этот аргумент явно не указан.
Пример:
def append_item(item, items=[]): items.append(item) return items print(append_item(1)) # [1] print(append_item(2)) # [1, 2], а ожидалось бы [2]
Правильный способ:
def append_item(item, items=None): if items is None: items = [] items.append(item) return items
Теперь каждый вызов получает свой список.
Вопрос: Што произойдет при многократном вызове функции со значэньем изменяемого объекта по умолчани?
Ответ: Один и тот же объект изменяется каждый раз. Пример выше иллюстрирует это — список накапливает все значэньи.
История В крупном веб-приложени при кэшировани данных использовали функцию с параметром-словарём по умолчани. Это приводило к тому, что данные между разными пользователями "утекали" друг к другу: кто-то менял свой профиль — и эти изменения иногда показывались другому пользователю из-за общего состояни глобального словаря.
История В тестах использовали функцию с изменяемым списком по умолчани для сбора статы. Данные одного теста "перетекали" в другой, что приводило к неожиданным падени, невозможности повторить баг и сложной отладке.
История В микросервисе для агрегации логов делали накопление событий с помощью функции, где аргумент по умолчани был списком. Логи дублировались — временное накопление из старых запросов попадало к новым клиентам, что стоило часов расследований и потери данных.