Vielleicht hilft ja dieses sinnfreie Minimalbeispiel:
Code: Alles auswählen
In [5]: def f(parrot, spam=[]):
...: spam.append(parrot)
...: return spam
...:
In [6]: f.func_defaults
Out[6]: ([],)
In [7]: f(42)
Out[7]: [42]
In [8]: f.func_defaults
Out[8]: ([42],)
In [9]: f(23)
Out[9]: [42, 23]
In [10]: f.func_defaults
Out[10]: ([42, 23],)
In [11]: f(4711, [])
Out[11]: [4711]
In [12]: f.func_defaults
Out[12]: ([42, 23],)
In [13]: f.func_defaults[0][0] = 'hallo'
In [14]: f('welt')
Out[14]: ['hallo', 23, 'welt']
Immer wenn man jetzt `f()` ohne ein Argument für `spam` aufruft wird diese Liste an den lokalen Namen `spam` gebunden. Ansonsten halt der Wert den man übergeben hat.
Wenn man das Objekt in der Methode verändert, nun ja, dann verändert man natürlich das Objekt. Wie man sowohl am Effekt bei den Aufrufen, als auch beim nachsehen in den Funktionsinterna deutlich sehen kann. Und wenn man direkt in den Innereien herum pfuscht, sieht man das natürlich auch bei den folgenden Aufrufen.