TGTGInsighttelegram intelligenceLIVE / telegram public index
← Python Заметки
Python Заметки avatar

TGINSIGHT POST

Post #371

@pythonotes

Python Заметки

Прегледи1,390Број на прегледи
Објавено10 јул.10.07.2024 г., 09:07
Содржина

Содржина на објавата

Три способа создать декоратор для метода класса. ▫️Способ 1. Обычная функция. Единственное отличие от простого декоратора функции в том, что нужно учитывать аргумент self. Если же он не нужен то просто пробрасываем его через *args def decorator_func(func): def wrapped(*args, **kwargs): print('decorator_func') return func(*args, **kwargs) return wrapped class MyClass: @decorator_func def method(self): print('call method') MyClass().method() # decorator_func # call method ▫️Способ 2. Методы класса. Но что, если декоратор жестко привязан к классу и используется только в нём. И стоит задача закрепить декоратор именно за этим классом и расположить внутри него. В таком случае можно сделать staticmethod. Это будет выглядеть страшно, но работать будет (тестировано на 3.11) Очевидно, что декоратор должен быть объявлен раньше метода. class MyClass: @staticmethod def decorator(func): def wrapper(*args, **kwargs): print('decorator from staticmethod') return func(*args, **kwargs) return wrapper @decorator.__func__ def method(self): print('method called') MyClass().method() # decorator from staticmethod # method called Тоже самое будет и с classmethod, но еще хуже. class MyClass: @classmethod def decorator(func): def wrapper(self, *args, **kwargs): print('decorator from classmethod') return func(self, *args, **kwargs) return wrapper @decorator.__func__ def method(self): print('method called') MyClass().method() # decorator from classmethod # method called Где-то потерялся аргумент cls. Скорее всего это можно решить но лучше не надо. Оба варианта выглядят страшненько 🫣 ▫️Способ 3. Вложенный класс и staticmethod class MyClass: class deco: @staticmethod def my_decorator(func): def wrapper(*args, **kwargs): print('decorator from subclass') return func(*args, **kwargs) return wrapper @deco.my_decorator def method(self): print('method called') MyClass().method() # decorator from subclass # method called Получаем чтото вроде микса способов 1 и 2: функция вложена в отдельный класс. Лучшей практикой является способ 1 - обычные функции. Всего пару раз за практику я использовал 3й способ, когда декоратор был намертво привязан к классу и нигде больше не мог использоваться (например, отправлял вызов метода на воркера в другой процесс, не спрашивайте почему так, просто так было нужно 🤪) Способ 2 не советую. Это, скорей, разминка для ума чем практический пример. PS - wraps пропустил для краткости - в коментах дополнительная инфа #tricks