Decorator python
Я не понимаю работу декораторов, что происходит когда внутри декоратора вызываем декорируемую функцияю а если не вызывать? Что если, когда это делать при много декораторов, объясните их работу пожалуйста
Ответы (1 шт):
Я понимаю это так.
Когда файл выполняется (при import тоже происходит выполнение импортируемого модуля), то по результату выполнения в пространстве имен появляются разные функции, классы и так далее. В зависимости от нужных нам условий (например win/linux) мы можем конструировать нужные нам классы и функции.
Все эти def/class - специальные конструкции для создания "на лету" объектов функций и классов - и для этого вызываются внутренние механизмы для построения этих сущностей (в случае классов это встроенная функция type()).
И вот если встречается декоратор, то при конструировании объекта функции или класса (не путать с экземплярами) дополнительно вызывается функция декоратора, которой передается декорируемая функция/класс и с ними можно что-то сделать.
Обычно делают обертку над функцией чтобы контролировать доступ к функции, но на самом деле можно буквально сделать что угодно.
Например:
def my_decorator(func):
class Foo:
def run(self):
print('i am class foo')
return Foo
@my_decorator
def hello():
print("hello!")
obj = hello()
obj.run()
Тут мы принимаем декорируемую функцию hello, игнорируем ее и конструируем класс.
А можем в декораторе сделать даже return 1 и у нас вместо функции hello будет определена переменная hello типа int со значенем 1
То есть декораторы являются возможностью вмешаться в механизм конструирования объекта и выполнить любые нужные нам действия.
Например, если мы пишем свой webapi, то можем сделать декоратор @route('/api'), который не будет ничего оборачивать, а зарегистрирует функцию в роутере, а если свой orm, то создаем маппинг для модели. А декоратор abstractmethod всего лишь добавляет к функции аттрибут funcobj.__isabstractmethod__ = True и ничего более.
Если же декораторов много, то вызваны они будут в обратном от определения порядке и каждой функции декоратора будет передан результат предыдущей
def my_decorator(func):
return "a"
def my_decorator2(func):
return 1
@my_decorator
@my_decorator2
def hello():
print("hello!")
Первым будет вызван my_decorator2 и получит как параметр функцию hello, а вторым будет вызван my_decorator и получит как параметр int (то, что вернула функция my_decorator2)
update: Подправил пост. Все-таки хоть декораторы и метаклассы по смыслу похожи, но декоратор получает уже сконструированный объект функции или класса, а метаклассы заменяют сам процесс создания.