使用装饰器在定义的函数上产生 NameError

Using decorator yields NameError on a defined function

为什么会这样:

def fn(proc, *args, **kwargs):
    cache = proc.cache = {}
    def cached_execution(cache, *args, **kwargs):
        if proc in cache:
            if args in cache[proc]:
                return cache[proc][args]
        res = proc(args)
        cache[proc] = {args: res}
        return res
    return cached_execution(cache, proc, *args, **kwargs)

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

print cached_fibo(100)

抛出这样的异常:

NameError: global name 'cached_fibo' is not defined

我缺少什么基本概念?

(概念上,**kwargs仅用于装饰。不用于检索缓存结果,但请不要担心)。

包装器似乎有点畸形。这是一个更新版本:

def fn(proc):
    cache = proc.cache = {}

    def cached_execution(*args, **kwargs):
        if proc in cache:
            if args in cache[proc]:
                return cache[proc][args]
        res = proc(args[0])
        cache[proc] = {args: res}
        return res
    return cached_execution

您试图 运行 包装器内部的包装器函数,而不是将其返回为 运行 作为函数,这导致了问题。

下一个问题是您提供的参数是 proc(args) 处的元组列表 *args 而您只想要第一个,因此需要变成 proc(args[0])

装饰器应该return一个函数,而不是调用函数的结果。 但这会导致我们犯下一个错误:当您将 cacheproc 传递给 cached_execution 函数时,它们落在 *args 中,后者又被传递给 proc.这没有意义。只需在内部方法中捕获 cacheproc 即可:

def fn(proc, *args, **kwargs):
    cache = proc.cache = {}
    def cached_execution(*args, **kwargs):
        if proc in cache:
            if args in cache[proc]:
                return cache[proc][args]
        res = proc(*args)
        cache[proc] = {args: res}
        return res
    return cached_execution

另一个问题:您没有打开包装 args。您应该调用 proc(*args) 而不是 proc(args) (已在上面修复)。