Марк Лутц - "Изучаем Python", глава 17 «Области видимости и вложенные функции» и раздел «Типичные ошибки при работе с функциями» в конце.
Значения по умолчанию для аргументов функции вычисляются и
запоминаются в момент выполнения инструкции def, а не при вызове
функции. Внутренняя реализация Python сохраняет по одному объекту для
каждого аргумента со значением по умолчанию, присоединенного к
функции.
Например, следующая функция использует пустой список в качестве
значения по умолчанию своего аргумента, а затем изменяет его при
каждом вызове:
>>> def saver(x=[]): # Объект списка сохраняется
... x.append(1) # При каждом вызове изменяется один и тот же объект!
... print(x)
...
>>> saver([2]) # Значение по умолчанию не используется
[2, 1]
>>> saver() # Используется значение по умолчанию
[1]
>>> saver() # Список растет при каждом вызове!
[1, 1]
>>> saver()
[1, 1, 1]
Если такое поведение является неприемлемым, можно просто создавать
копию аргумента по умолчанию в начале тела функции или переместить
выражение, возвращающее значение по умолчанию, в тело функции.
Поскольку в этом случае значение по умолчанию будет находиться в
программном коде, который выполняется при каждом вызове функции, вы
всякий раз будете получать новый объект:
>>> def saver(x=None):
... if x is None: # Аргумент отсутствует?
... x = [] # Создать новый список
... x.append(1) # Изменить объект списка
... print(x)
...
>>> saver([2])
[2, 1]
>>> saver() # Список больше не растет
[1]
>>> saver()
[1]