问题描述
这是一个使用缓存计算阶乘数的程序。
def run_closure():
f = cache(factorial)
print("5! = %d" % f(5))
print("5! = %d" % f(5))
print("4! = %d" % f(4))
pass
def run_decorator():
print("5! = %d" % factorial(5))
print("5! = %d" % factorial(5))
print("4! = %d" % factorial(4))
pass
def cache(func):
table = {}
def wrapper(n):
if n in table:
print("%d is in memo." % n)
return table[n]
else:
print("f(%d) is called." % n)
table[n] = func(n)
return table[n]
return wrapper
# @cache # comment for "run_closure()"; uncomment for "run_decorator"
def factorial(n):
if n == 0:
return 1
else:
return n * factorial(n - 1)
def main():
run_closure()
# run_decorator()
pass
if __name__ == "__main__":
main()
pass
f(5) 被调用。
5! = 120
5 在备忘录中。
5! = 120
f(4) 被调用。
4! = 24
后面的输出:
f(5) 被调用。
f(4) 被调用。
f(3) 被调用。
f(2) 被调用。
f(1) 被调用。
f(0) 被调用。
5! = 120
5 在备忘录中。
5! = 120
4 在备忘录中。
4! = 24
在前一种情况下,当计算 5!
时,前一个 n!(n<5)
应该已经计算并保存到 table
中,但它没有。后一种情况是我想要的。那么闭包和装饰器有什么区别呢?任何帮助表示赞赏。
解决方法
使用装饰器,您可以更改函数本身,并递归调用其新版本。在使用闭包的方式时,它的行为有所不同:您创建函数 f,它在内部不断调用 data = await rootBundle.load("assets/app.db");
。如果您设置 factorial
,它将与装饰的行为完全相同。
一般意义上的装饰器是环绕另一个对象的函数或类,用于扩展或装饰该对象。装饰器支持与包装函数或对象相同的接口,因此接收者甚至不知道对象已被装饰。
闭包是一个匿名函数,它引用其范围之外的参数或其他变量。
所以基本上,装饰器使用闭包,而不是替换它们。