有没有语法糖的Python装饰器之间的区别?

时间:2015-12-10 12:20:44

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

我正在尝试实现一个记忆任意函数的装饰器。看来我已成功完成了以下代码:

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)

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

1 个答案:

答案 0 :(得分:3)

您的递归调用未被记忆,因为您使用了新名称,而不是原始的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之外从未绑定到原始函数。