微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Python中闭包和装饰器的区别

如何解决Python中闭包和装饰器的区别

这是一个使用缓存计算阶乘数的程序。

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,它将与装饰的行为完全相同。

,

一般意义上的装饰器是环绕另一个对象的函数或类,用于扩展或装饰该对象。装饰器支持与包装函数或对象相同的接口,因此接收者甚至不知道对象已被装饰。

闭包是一个匿名函数,它引用其范围之外的参数或其他变量。

所以基本上,装饰器使用闭包,而不是替换它们。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。