Почему декоратор экземпляра класса пропускает код?

#python

Вопрос:

Попробуйте выполнить приведенный ниже код. Почему на выходе выводится только «пропускается» один раз? Мы вызываем rotate_list три раза, и я не понимаю, почему он не запускает весь код внутри __call__() каждый раз. Я предполагаю, что он печатает его только один раз для создания экземпляра или что-то в этом роде.

 class anothercall:
    def __init__(self):
        self.enabled = True
    def __call__(self,f):
        print("gets skipped")
        
        def wrap(*args, **kwargs):
            if self.enabled:
                print('calling {}'.format(f))
            return f(*args, **kwargs)
        return wrap

another = anothercall()
@another
def rotate_list(l):
    return l[1:]   [l[0]]
    
l = [1,2,3]
rotate_list(l)
l = [1,2,3]
rotate_list(l)
l = [1,2,3]
rotate_list(l)
 

Комментарии:

1. Вы оформили только одну функцию, поэтому декоратор вызывается только один раз.

Ответ №1:

another вызывается, когда вы определяете rotate_list , а не когда вы вызываете rotate_list . Имя rotate_list -отскок к тому, что another возвращается.

 @another
def rotate_list(l):
    ...
 

эквивалентно

 def rotate_list(l):
    ...

rotate_list = another(rotate_list)
 

Ответ №2:

Когда интерпретатор python сталкивается с функцией с помощью декоратора, он изменяет функцию с помощью функции-оболочки. Для вашей программы rotate_list = another(rotate_list) это произойдет в строке 14. Это вызов __call__ метода, так что печать «пропускается» один раз.

Затем, когда вы вызываете rotate_list функцию, это просто вызывающая wrap функция.