装饰递归函数

时间:2016-09-24 17:44:52

标签: python python-3.x decorator scoping

编辑:我没有很好地解释我的问题。我对如何使用闭包感到困惑,函数似乎记得它以前的环境,但是通过递归调用它似乎找到了名称的更新值。

Thomas Ballinger "Finding closure with closures" talk完全解决了我的困惑:

  

变量的范围根据定义确定,变量的值在执行时确定。

因此,无论是递归还是闭包,名称的绑定都是在定义时定义的,但之后的值仍然可以更新。

原始问题:

装饰器可以在没有任何额外工作的情况下处理递归函数:

def debug(f):
    def new_f(*args, **kwargs):
        print('arguments:', *args, **kwargs)
        return f(*args, **kwargs)
    return new_f

@debug
def f(n):
    if n > 1:
        return f(n-1)*n # f refers to the decorated version!
    else:
        return 1

python中的哪种机制可以确保行f中的return f(n-1)*n指向f的装饰版本而不是原始版本?

我认为函数在定义它时会记住它的上下文(因此,对于闭包,内部函数可以使用外部函数中的对象)。但是当f被定义时,装饰器还没有被应用,所以不应该在{/ 1}} 里面函数f永远引用未修饰的版本?显然,我误解了函数范围/上下文规则中的某些内容,但是什么呢?

1 个答案:

答案 0 :(得分:2)

当函数执行时,python将查找名称f(并且当编译它时)并且看到它是装饰版:

>>> f
<function __main__.debug.<locals>.new_f>

由于名称f基本上是通过应用装饰器重新绑定的,所以只要查找其名称就会使用f