编辑:我没有很好地解释我的问题。我对如何使用闭包感到困惑,函数似乎记得它以前的环境,但是通过递归调用它似乎找到了名称的更新值。
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
永远引用未修饰的版本?显然,我误解了函数范围/上下文规则中的某些内容,但是什么呢?
答案 0 :(得分:2)
当函数执行时,python将查找名称f
(并且当编译它时不)并且看到它是装饰版:
>>> f
<function __main__.debug.<locals>.new_f>
由于名称f
基本上是通过应用装饰器重新绑定的,所以只要查找其名称就会使用f
。