@Vlad1987
учу Python

В чём отличие @Decorator от @Decorator()?

объясните, пожалуйста, почему если в нижеуказанном коде написать @FuncDec(), то всё работает, а если написать @FuncDec, то интерпретатор орёт, что в__init__ подали 2 аргумента вместо одного?
Не понимаю, что меняется, когда я ставлю скобки...
Я знаю, что есть декораторы с параметрами, там наличие этих скобок оправдано, но как они работают, в случае, когда остаются пустыми?

from functools import wraps


class FuncDec:
    def __init__(self):
        pass

    def __call__(self, f):
        @wraps(f)
        def wrapper(*args, **kwargs):
            f(*args, **kwargs)
            print('I am working properly')
        return wrapper


@FuncDec()
def foo():
    print('Hello')


foo()

# Hello
# I am working properly
  • Вопрос задан
  • 323 просмотра
Решения вопроса 1
Assargin
@Assargin
Перед ответом смотрю наличие ✔ в ваших вопросах
Декоратор - это функция, которой на вход подаётся функция и вернуть он должен тоже функцию. Например:
@decorator 
def foo():
 ..

Эквивалентно foo = decorator(foo)

Теперь про случай из вопроса. В качестве декоратора вместо обычной функции вы используете класс (точнее его объект):
@FuncDec()
def foo():
    print('Hello')

Эквивалентно foo = FuncDec()(foo), а именно:
  • создаётся объект FuncDec (вызывается конструктор __init__)
  • этот объект вызывается (__call__) вместе с параметром foo
  • объект вернул функцию wrapper, которая и будет в дальнейшем выполняться вместо объявленной foo
  • профит

Но если убрать скобки, то получится эквивалент foo = FuncDec(foo)
То есть просто вызов конструктора, который у вас не принимает параметров - поэтому и ругается.
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы