【问题标题】:Difference between Python decorator with and without syntactic sugar?有和没有语法糖的 Python 装饰器之间的区别?
【发布时间】:2016-03-16 01:57:30
【问题描述】:

我正在尝试实现一个可以记忆任意函数的装饰器。看来我已经使用以下代码成功地实现了这一点:

def memoize(func):
    cache = {}
    def wrapper(*args, **kwargs):
        acc = ""
        for arg in args:
            acc += str(arg)
        if acc in cache:
            return cache[acc]
        else:
            cache[acc] = func(*args, **kwargs)
            return cache[acc]
    return wrapper

@memoize
def fib(n):
    if n == 0 or n == 1:
        return 1
    else:
        return fib(n - 1) + fib(n - 2)

然后fib(100) 很快返回573147844013817084101。但是,如果我不使用语法糖:

def fib(n):
    if n == 0 or n == 1:
        return 1
    else:
        return fib(n - 1) + fib(n - 2)
memoized = memoize(fib)
print memoized(100)

函数挂起。调试它,看起来返回的包装器无法修改缓存。有人可以解释这种行为吗?据我所知,使用糖和不使用糖之间应该没有区别。

【问题讨论】:

    标签: python functional-programming decorator python-decorators memoization


    【解决方案1】:

    您的递归调用没有被记忆,因为您使用了一个新名称,而不是原来的fib 函数名称。每个fib() 迭代都会回调fib(),但这会调用原始的、未修饰的函数

    将装饰器调用的返回值分配给fib

    def fib(n):
        if n == 0 or n == 1:
            return 1
        else:
            return fib(n - 1) + fib(n - 2)
    fib = memoize(fib)
    print fib(100)
    

    或者,如果您必须使用memoize 作为装饰器结果的名称,则让fib() 调用memoized() 进行递归调用:

    def fib(n):
        if n == 0 or n == 1:
            return 1
        else:
            return memoized(n - 1) + memoizzed(n - 2)
    memoized = memoized(fib)
    print memoized(100)
    

    请记住,@decorator 语法分配给相同的名称,而不是新名称。以下两个是等价的:

    @memoize
    def fib(n):
        # ....
    

    def fib(n):
        # ....
    fib = memoize(fib)  # Same name!
    

    除了名称 fib 永远不会首先绑定到原始函数。

    【讨论】:

      猜你喜欢
      • 2018-09-01
      • 2012-01-09
      • 1970-01-01
      • 2012-08-31
      • 2018-11-22
      • 2017-04-21
      • 2015-12-12
      • 2020-12-10
      • 2014-04-27
      相关资源
      最近更新 更多