Декораторы классов Python — как работают и примеры
В этом руководстве вы узнаете, как работают декораторы классов Python. После урока вы научитесь определять классы в качестве декораторов.
Введение в декораторы классов Python
Вы узнаете, как использовать функции для определения декораторов. Например, следующая функция звездочки выводит несколько символов * до и после вызова декорированной функции:
def star(n): def decorate(fn): def wrapper(*args, **kwargs): print(n*'*') result = fn(*args, **kwargs) print(result) print(n*'*') return result return wrapper return decorate
Звездочка — фабрика декораторов, которая возвращает декоратор. Он принимает аргумент, указывающий количество отображаемых символов *.
Ниже показано, как использовать фабрику декоратора *:
@star(5) def add(a, b): return a + b add(10, 20)
Выход:
***** 30 *****
Фабрика декораторов star() принимает аргумент и возвращает вызываемый объект. Вызываемый объект принимает аргумент(fn), который представляет собой функцию, которая будет декорирована. Кроме того, вызываемый объект может получить доступ к аргументу(n), переданному фабрике декораторов.
Экземпляр класса может быть вызываемым, если он реализует метод __call__. Поэтому вы можете сделать метод __call__ декоратором.
В следующем примере фабрика декораторов перезаписывается с использованием вместо этого класса:
class Star: def __init__(self, n): self.n = n def __call__(self, fn): def wrapper(*args, **kwargs): print(self.n*'*') result = fn(*args, **kwargs) print(result) print(self.n*'*') return result return wrapper
И вы можете использовать класс Star в качестве декоратора следующим образом:
@Star(5) def add(a, b): return a + b
@Star(5) возвращает экземпляр класса Star. Этот экземпляр является вызываемым, поэтому вы можете сделать что-то вроде:
add = Star(5)(add)
Таким образом, вы можете использовать вызываемые классы для декорирования функций.
Положим все это вместе:
from functools import wraps class Star: def __init__(self, n): self.n = n def __call__(self, fn): @wraps(fn) def wrapper(*args, **kwargs): print(self.n*'*') result = fn(*args, **kwargs) print(result) print(self.n*'*') return result return wrapper @Star(5) def add(a, b): return a + b add(10, 20)