Als Antwort auf die Frage nach guten Verwendungsmöglichkeiten für veränderbare Standardargumentwerte biete ich das folgende Beispiel an:
Eine veränderbare Standardeinstellung kann nützlich sein, um benutzerfreundliche, importierbare Befehle Ihrer eigenen Erstellung zu programmieren. Die veränderbare Standardmethode besteht darin, private, statische Variablen in einer Funktion zu haben, die Sie beim ersten Aufruf initialisieren können (ähnlich wie bei einer Klasse), ohne jedoch auf Globals zurückgreifen zu müssen, ohne einen Wrapper verwenden zu müssen und ohne a instanziieren zu müssen Klassenobjekt, das importiert wurde. Es ist auf seine Weise elegant, wie ich hoffe, dass Sie zustimmen werden.
Betrachten Sie diese beiden Beispiele:
def dittle(cache = []):
from time import sleep
if type(cache) != list or cache !=[] and (len(cache) == 2 and type(cache[1]) != int):
print(" User called dittle("+repr(cache)+").\n >> Warning: dittle() takes no arguments, so this call is ignored.\n")
return
if not cache:
print("\n cache =",cache)
print(" Initializing private mutable static cache. Runs only on First Call!")
cache.append("Hello World!")
cache.append(0)
print(" cache =",cache,end="\n\n")
cache[1]+=1
outstr = " dittle() called "+str(cache[1])+" times."
if cache[1] == 1:outstr=outstr.replace("s.",".")
print(outstr)
print(" Internal cache held string = '"+cache[0]+"'")
print()
if cache[1] == 3:
print(" Let's rest for a moment.")
sleep(2.0)
print(" Wheew! Ready to continue.\n")
sleep(1.0)
elif cache[1] == 4:
cache[0] = "It's Good to be Alive!"
if __name__ == "__main__":
for cnt in range(2):dittle()
print(" Attempting to pass an list to dittle()")
dittle([" BAD","Data"])
print(" Attempting to pass a non-list to dittle()")
dittle("hi")
print(" Calling dittle() normally..")
dittle()
print(" Attempting to set the private mutable value from the outside.")
dittle([" I am a Grieffer!\n (Notice this change will not stick!)",-7])
print(" Calling dittle() normally once again.")
dittle()
dittle()
Wenn Sie diesen Code ausführen, werden Sie feststellen, dass die Funktion dittle () beim ersten Aufruf verinnerlicht wird, jedoch nicht bei zusätzlichen Aufrufen. Sie verwendet einen privaten statischen Cache (die veränderbare Standardeinstellung) für die interne statische Speicherung zwischen Aufrufen und lehnt Entführungsversuche ab Der statische Speicher ist widerstandsfähig gegen böswillige Eingaben und kann auf der Grundlage dynamischer Bedingungen (hier abhängig davon, wie oft die Funktion aufgerufen wurde) handeln.
Der Schlüssel zur Verwendung veränderlicher Standardeinstellungen besteht darin, nichts zu tun, was die Variable im Speicher neu zuweist, sondern die Variable immer an Ort und Stelle zu ändern.
Speichern Sie dieses erste Programm in Ihrem aktuellen Verzeichnis unter dem Namen "DITTLE.py" und führen Sie das nächste Programm aus, um die potenzielle Leistungsfähigkeit und Nützlichkeit dieser Technik wirklich zu erkennen. Es importiert und verwendet unseren neuen Befehl dittle (), ohne dass Schritte zum Erinnern oder Programmieren von Reifen zum Durchspringen erforderlich sind.
Hier ist unser zweites Beispiel. Kompilieren Sie dieses und führen Sie es als neues Programm aus.
from DITTLE import dittle
print("\n We have emulated a new python command with 'dittle()'.\n")
dittle()
dittle()
dittle()
dittle()
dittle()
Ist das nicht so glatt und sauber wie möglich? Diese veränderlichen Standardeinstellungen können sehr nützlich sein.
========================
Nachdem ich eine Weile über meine Antwort nachgedacht habe, bin ich mir nicht sicher, ob ich den Unterschied zwischen der Verwendung der veränderlichen Standardmethode und der regulären Methode, dasselbe zu erreichen, klar gemacht habe.
Normalerweise wird eine importierbare Funktion verwendet, die ein Klassenobjekt umschließt (und ein globales Objekt verwendet). Zum Vergleich hier eine klassenbasierte Methode, die versucht, die gleichen Aktionen wie die veränderbare Standardmethode auszuführen.
from time import sleep
class dittle_class():
def __init__(self):
self.b = 0
self.a = " Hello World!"
print("\n Initializing Class Object. Executes on First Call only.")
print(" self.a = '"+str(self.a),"', self.b =",self.b,end="\n\n")
def report(self):
self.b = self.b + 1
if self.b == 1:
print(" Dittle() called",self.b,"time.")
else:
print(" Dittle() called",self.b,"times.")
if self.b == 5:
self.a = " It's Great to be alive!"
print(" Internal String =",self.a,end="\n\n")
if self.b ==3:
print(" Let's rest for a moment.")
sleep(2.0)
print(" Wheew! Ready to continue.\n")
sleep(1.0)
cl= dittle_class()
def dittle():
global cl
if type(cl.a) != str and type(cl.b) != int:
print(" Class exists but does not have valid format.")
cl.report()
if __name__ == "__main__":
print(" We have emulated a python command with our own 'dittle()' command.\n")
for cnt in range(2):dittle()
print(" Attempting to pass arguments to dittle()")
try:
dittle(["BAD","Data"])
except:
print(" This caused a fatal error that can't be caught in the function.\n")
print(" Calling dittle() normally..")
dittle()
print(" Attempting to set the Class variable from the outside.")
cl.a = " I'm a griefer. My damage sticks."
cl.b = -7
dittle()
dittle()
Speichern Sie dieses klassenbasierte Programm in Ihrem aktuellen Verzeichnis als DITTLE.py und führen Sie dann den folgenden Code aus (der mit dem vorherigen identisch ist).
from DITTLE import dittle
dittle()
dittle()
dittle()
dittle()
dittle()
Durch den Vergleich der beiden Methoden sollten die Vorteile der Verwendung eines veränderlichen Standards in einer Funktion klarer werden. Die veränderbare Standardmethode benötigt keine Globalen, ihre internen Variablen können nicht direkt festgelegt werden. Und während die veränderbare Methode ein sachkundiges übergebenes Argument für einen einzelnen Zyklus akzeptierte und es dann abschüttelte, wurde die Class-Methode dauerhaft geändert, da ihre interne Variable direkt nach außen verfügbar ist. Welche Methode ist einfacher zu programmieren? Ich denke, das hängt von Ihrem Komfortniveau mit den Methoden und der Komplexität Ihrer Ziele ab.