This question already has answers here:
Decorating recursive functions in python
                                
                                    (5个答案)
                                
                        
                                3年前关闭。
            
                    
编辑:我没有很好地解释我的问题。我对使用闭包感到困惑,该函数似乎还记得其先前的环境,但是对于递归调用,它似乎是在查找名称的更新值。

我的困惑已通过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时,还没有应用装饰器,因此函数f中的f难道不永远引用未修饰的版本吗?显然,我对函数作用域/上下文规则有误解,但是呢?

最佳答案

python在执行函数时(而不是在编译时)会查找名称f的事实,并看到它是修饰版本:

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


由于名称f实际上是通过应用装饰器重新绑定的,因此,只要查找其名称,就会使用f

09-10 05:42
查看更多