Python 装饰器-更改变量名

Python 装饰器-更改变量名,python,python-decorators,Python,Python Decorators,我正在学习Python中装饰器的概念。我想我已经浏览了很多博客,对装饰师的工作原理以及我们为什么需要装饰师有了一些基本的了解 在这样做的过程中,我遇到了一个教程(完全没有提到这一点),作者在解释decorators时写道: def call_counter(func): def helper(x): helper.calls += 1 return func(x) helper.calls = 0 return help

我正在学习Python中装饰器的概念。我想我已经浏览了很多博客,对装饰师的工作原理以及我们为什么需要装饰师有了一些基本的了解

在这样做的过程中,我遇到了一个教程(完全没有提到这一点),作者在解释decorators时写道:

def call_counter(func):
    def helper(x):          
        helper.calls += 1
        return func(x)
    helper.calls = 0
    return helper

def succ(x):
    return x + 1

succ = call_counter(succ)
print(succ.calls)
for i in range(10):
    succ(i)
print(succ.calls)  
输出:

0
10
正如我前面提到的,我本以为我了解装饰师的工作原理和基本Python,但突然在这里怀疑我自己

在helper函数中,作者将
helper.calls
变量递增1(根据我之前的理解,这应该只是一个普通变量,
helper.
只是显示此变量在
helper
函数中),但只定义了
helper.calls
,在这里使用后,快结束了

类似地,在调用decorator函数之后,作者突然使用了
succ.calls
变量,甚至打印了预期的结果,但没有任何定义

顺便说一句,我已经试着做了我的研究,但甚至不能用恰当的语言来表达这种行为,以找到任何合适的方式

p.p.S.无法给出更精确的标题,因为完全不了解实际发生的现象

succ = call_counter(succ)  # succ.calls = 0 when function is called (succ = helper)
print(succ.calls)  # prints 0
for i in range(10):
    succ(i)  # As succ = helper now, this becomes helper(i) and helper.i is incremented by 1 each iteration, succ(x) is then returned after as func = succ and x + 1 is returned from succ(x)
print(succ.calls)  # prints 10 as helper.calls is incremented 10 times within the loop

如果succ(x)没有返回任何值,因为它没有在其他任何地方使用,则可以实现相同的输出,您可以在

上看到可视化的代码缩进被破坏,并且我没有看到装饰符…变量由
helper.calls=0
inside
call\u counter()
行定义。这个嵌套函数
helper
call_counter()
返回,并分配给全局变量
suc
,因此
suc.calls
现在引用与
helper.calls
@jasonharper>相同的变量。尽管如此,helper.calls=0是在代码后面定义的,而我在定义helper.calls之前进入helper函数。我应该在我的问题中明确提到这一点。另外,请您进一步介绍全局变量succ,以及helper.calls tans的名称如何转换为全新的变量succ.calls。这类作业是否有名称-供我进一步学习。
call\u counter()
定义
helper()
(但不调用它),将
calls
属性添加到它,然后返回它。顶级代码然后将该返回值分配给
succ
。由于
helper
succ
是同一对象的两个名称,
helper.calls
succ.calls
同样是同一对象的两个名称-这里没有进一步的指定。感谢@jasonharper解释了这一切。它是decorators或嵌套函数的基础,我以为我已经介绍过了,但没有提到这样一个概念,即不仅函数名指向同一个片段,而且functionname.attribute也将指向包装函数中的同一个对象。