修饰递归函数
Decorating a recursive function
编辑:我没有很好地解释我的问题。我对如何使用闭包感到困惑,该函数似乎记得它以前的环境,但是通过递归调用它似乎找到了名称的更新值。
我的困惑被Thomas Ballinger "Finding closure with closures" talk完美解决了:
Scope of a variable is determined at definition, value of a variable is determined at execution.
因此无论是递归还是闭包,名称的绑定都是在定义时定义的,但值仍然可以在之后更新。
原问题:
装饰器无需任何额外努力即可处理递归函数:
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 中的什么机制确保行 return f(n-1)*n
中的 f
指向 f
的修饰版本而不是原始版本?
我认为函数在定义时会记住它的上下文(这样通过闭包,内部函数可以使用外部函数中的对象)。但是在定义f
的时候,装饰器还没有应用,所以f
里面函数f
不应该引用未装饰的永远的版本?显然,我误解了函数作用域/上下文规则中的某些内容,但是什么?
当函数 执行 时 python 将查找名称 f
的事实(而 不会 编译的时候)看到是装饰版:
>>> f
<function __main__.debug.<locals>.new_f>
由于名称 f
本质上是通过应用装饰器重新绑定的,因此只要查找其名称,就会使用 f
。
编辑:我没有很好地解释我的问题。我对如何使用闭包感到困惑,该函数似乎记得它以前的环境,但是通过递归调用它似乎找到了名称的更新值。
我的困惑被Thomas Ballinger "Finding closure with closures" talk完美解决了:
Scope of a variable is determined at definition, value of a variable is determined at execution.
因此无论是递归还是闭包,名称的绑定都是在定义时定义的,但值仍然可以在之后更新。
原问题:
装饰器无需任何额外努力即可处理递归函数:
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 中的什么机制确保行 return f(n-1)*n
中的 f
指向 f
的修饰版本而不是原始版本?
我认为函数在定义时会记住它的上下文(这样通过闭包,内部函数可以使用外部函数中的对象)。但是在定义f
的时候,装饰器还没有应用,所以f
里面函数f
不应该引用未装饰的永远的版本?显然,我误解了函数作用域/上下文规则中的某些内容,但是什么?
当函数 执行 时 python 将查找名称 f
的事实(而 不会 编译的时候)看到是装饰版:
>>> f
<function __main__.debug.<locals>.new_f>
由于名称 f
本质上是通过应用装饰器重新绑定的,因此只要查找其名称,就会使用 f
。