Відповідаючи на запитання щодо ефективного використання змінних значень аргументів за замовчуванням, я пропоную такий приклад:
Змінюваний за замовчуванням може бути корисним для програмування простих у використанні команд, що імпортуються, власного створення. Змінюваний метод за замовчуванням має приватні статичні змінні у функції, які ви можете ініціалізувати під час першого виклику (дуже схоже на клас), але без необхідності вдаватися до глобалів, без необхідності використовувати обгортку та без потреби створювати об'єкт класу, який було імпортовано. Це по-своєму елегантно, бо, сподіваюся, ви погодитесь.
Розглянемо ці два приклади:
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()
Якщо запустити цей код, ви побачите, що функція dittle () інтерналізується під час першого виклику, але не під час додаткових викликів, вона використовує приватний статичний кеш (змінний за замовчуванням) для внутрішнього статичного зберігання між викликами, відхиляє спроби викрадення статичне сховище, стійке до зловмисного введення і може діяти на основі динамічних умов (тут - від кількості викликів функції).
Ключ до використання змінних за замовчуванням не робить нічого, що призведе до перепризначення змінної в пам’яті, а завжди змінює змінну на місці.
Щоб справді побачити потенційну потужність та корисність цієї техніки, збережіть цю першу програму до поточного каталогу під назвою "DITTLE.py", а потім запустіть наступну програму. Він імпортує та використовує нашу нову команду dittle (), не вимагаючи жодних кроків для запам'ятовування або програмування обручів для переходу.
Ось наш другий приклад. Скомпілюйте та запустіть це як нову програму.
from DITTLE import dittle
print("\n We have emulated a new python command with 'dittle()'.\n")
dittle()
dittle()
dittle()
dittle()
dittle()
Тепер хіба це не так гладко та чисто? Ці змінні за замовчуванням дійсно можуть стати в нагоді.
==========================
Поміркувавши над моєю відповіддю деякий час, я не впевнений, що я зробив різницю між використанням змінного методу за замовчуванням та звичайним способом досягнення того ж самого.
Звичайним способом є використання імпортованої функції, яка обгортає об’єкт класу (і використовує глобальний). Отже, для порівняння, тут метод на основі класу, який намагається робити те саме, що і змінний метод за замовчуванням.
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()
Збережіть цю програму на основі класу у вашому поточному каталозі як DITTLE.py, а потім запустіть такий код (той самий, що і раніше.)
from DITTLE import dittle
dittle()
dittle()
dittle()
dittle()
dittle()
Порівнюючи два методи, переваги використання змінної за замовчуванням у функції повинні бути чіткішими. Змінюваний метод за замовчуванням не потребує глобалів, його внутрішні змінні неможливо встановити безпосередньо. І в той час як мутабельний метод прийняв добре переданий аргумент за один цикл, а потім відкинув його, метод Класу був остаточно змінений, оскільки його внутрішня змінна знаходиться безпосередньо назовні. Щодо того, який метод простіше програмувати? Я думаю, що це залежить від вашого рівня комфорту з методами та складності ваших цілей.