Bevor ich die Kühnheit habe, einen Fehlerbericht zu schreiben, dachte ich, ich würde hier meine Annahmen unter den klügeren Pythonistas überprüfen. Ich traf einen verwirrenden Fall heute, so dass ich schnitzte es zu einem Spielzeug Beispiel unten, unten gezeigt:Python-Funktionsaufrufe sind blutend, stateful, Parameter können nicht initialisiert werden?
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
A little script to demonstrate that a function won't re-initialize its
list parameters between calls, but instead allows them to retain state.
"""
def bleedscope(a=[], b=[]):
"""
On each call, unless explicitly passed, both `a` and `b` should be
initialized as empty lists.
"""
c = a
if b:
c.extend(b)
return len(c)
x = bleedscope(b=[1])
print x # Should be 1, as expected.
x = bleedscope(b=[2])
print x # Expect also to be 1, but it's 2. `a` is retained.
x = bleedscope(a=[1])
print x # Now 1 as expected.
x = bleedscope(b=[3])
print x # 1 as expected? No, it's 3! Insanity!
Ich dachte, Funktionsargumente beschränkt sich auf die Funktion lokal waren und am Ende einer Funktion Garbage Collection Ruf an, niemals den Zustand zwischen ihnen zu halten. Ich habe das obige Skript auf Python 2.5.2 und Python 2.6.1 getestet, und mein Verständnis führt nicht zu den Ergebnissen. Argument a
behält sicherlich den Status zwischen den meisten dieser Aufrufe; der am meisten verwirrende ist der letzte Anruf bei bleedscope
, wo er den Zustand des vorherigen Anrufs überspringt und zu dem Zustand am Ende des zweiten Anrufs zurückkehrt (d. h. [1, 2]
). [Ich schlage vor, dies in Ihrem bevorzugten Debugger auszuführen, um selbst zu sehen. Wenn Sie keinen haben, empfehle ich Winpdb als soliden FOSS Standalone Python Debugger.]
Was ist hier los?
Jedes veränderbare Objekt ist eine schlechte Wahl für einen Standardwert - veränderbare Objekte (wie Listen) können nicht auf diese Weise verwendet werden. –