为了回答可变默认参数值的合理使用问题,我提供以下示例:
可变的默认值对于编写自己创建的易于使用的可导入命令很有用。可变的默认方法相当于在函数中具有私有的静态变量,您可以在第一次调用时对其进行初始化(非常类似于类),而不必求助于全局变量,而不必使用包装器,也不必实例化a导入的类对象。我希望您能同意,它以自己的方式高雅。
考虑以下两个示例:
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()
通过比较这两种方法,在函数中使用可变默认值的优点应该更加清楚。可变的默认方法不需要全局变量,它的内部变量不能直接设置。尽管可变方法在一个周期内接受了一个知识渊博的传递参数,然后将其忽略了,但由于永久将Class方法的内部变量直接暴露给外部,因此对其进行了永久更改。至于哪种方法更容易编程?我认为这取决于您对方法的舒适程度和目标的复杂性。