Декоратор - изменение имени переменной - PullRequest
0 голосов
/ 15 января 2019

Я изучаю концепции декораторов в Python. В то время как я думаю, что я покрыл много блогов и получил некоторое общее представление о том, как работают декораторы и зачем он нам нужен.

При этом я наткнулся на учебник (полностью потерял ссылку на это), где, объясняя о декораторах, автор написал следующее:

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.calls на 1 (что, согласно моему предыдущему пониманию, должно быть просто обычной переменной, а helper. только для того, чтобы показать, что эта переменная находится внутри helper функции), но определил helper.calls только после его использования здесь, к концу.

Аналогично, ближе к концу, после вызова функции декоратора, автор внезапно использовал переменную succ.calls - которая даже печатает ожидаемый результат - но без какого-либо определения.

P.S. Я пытался сделать свое исследование, но даже не мог выразить это поведение в правильных словах, чтобы найти что-нибудь подходящее.

P.P.S. Не смог придумать более точный заголовок, так как совершенно незнаком с фактическим происходящим явлением.

1 Ответ

0 голосов
/ 15 января 2019
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) не вернул никакого значения, так как он больше нигде не использовался, вы можете увидеть ваш код, визуализированный на http://www.pythontutor.com/visualize.html#mode=edit

...