Почему опасно писать def f(x, arr=[])?
Создание функций с изменяемыми значениями по умолчанию в сигнатуре является классической ловушкой для разработчиков на языке Python, с которой рано или поздно сталкивается каждый программист. Распространенной ошибкой является написание кода вида функции со списком по умолчанию, когда аргумент инициализируется пустым списком прямо при объявлении.
Причина возникновения потенциальных проблем кроется в том, как именно устроен механизм интерпретатора Python. Значения по умолчанию для аргументов функций вычисляются ровно один раз в момент, когда интерпретатор читает и определяет функцию, а не каждый раз при ее непосредственном вызове в ходе выполнения программы.
В результате этого архитектурного решения один и тот же созданный в памяти список становится общим для всех последующих вызовов функции, если вызывающий код явно не передает свой собственный аргумент. Это приводит к накоплению данных между вызовами, что может полностью сломать логику работы приложения и вызвать труднодиагностируемые ошибки.
Правильным и безопасным подходом является использование в качестве значения по умолчанию специального маркера None с последующей инициализацией внутри тела функции. Аналогичное правило безопасности распространяется и на другие изменяемые типы данных встроенной библиотеки Python, такие как словари и множества.