6.1 Декораторы для методов классов
Декораторы также могут использоваться для методов классов. Важно помнить, что для методов классов необходимо правильно передавать аргументы self или cls.
Нюансы работы классов мы с вами еще не проходили, но хотелось бы, чтобы вы знали, что такая возможность у декораторов имеется.
def log_method_call(func):
def wrapper(self, *args, **kwargs):
print(f"Вызов метода {func.__name__}")
return func(self, *args, **kwargs)
return wrapper
class MyClass:
@log_method_call
def say_hello(self):
print("Hello from MyClass!")
obj = MyClass()
obj.say_hello()
Объяснение
Декоратор (log_method_call): Этот декоратор принимает метод func и возвращает новую функцию wrapper, которая выводит сообщение перед вызовом метода.
Метод класса с декоратором (say_hello): Метод say_hello обернут декоратором log_method_call, что добавляет дополнительное поведение при его вызове.
Вывод:
Вызов метода say_hello
Hello from MyClass!
6.2 Несколько декораторов
Вы можете использовать несколько декораторов для одной функции, накладывая их друг на друга. Декораторы применяются в порядке, обратном их объявлению.
def decorator1(func):
def wrapper():
print("Декоратор 1")
func()
return wrapper
def decorator2(func):
def wrapper():
print("Декоратор 2")
func()
return wrapper
@decorator1
@decorator2
def say_hello():
print("Hello!")
say_hello()
Объяснение
Декораторы (decorator1 и decorator2): Эти декораторы добавляют свои сообщения перед вызовом функции func.
Функция с декораторами (say_hello): Функция say_hello обернута обоими декораторами. Сначала применяется decorator2, затем decorator1.
Вывод:
# Декоратор 1
# Декоратор 2
Hello!
6.3 Встроенные декораторы
Python предоставляет несколько встроенных декораторов для стандартных задач, таких как статические методы, методы класса и свойства.
@staticmethod
Декоратор @staticmethod используется для создания статического метода, который не требует экземпляра класса для вызова.
class MyClass:
@staticmethod
def static_method():
print("Это статический метод.")
MyClass.static_method()
@classmethod
Декоратор @classmethod используется для создания метода класса, который принимает класс (а не экземпляр) в качестве первого аргумента.
class MyClass:
@classmethod
def class_method(cls):
print(f"Это метод класса {cls.__name__}.")
MyClass.class_method()
@property
Декоратор @property используется для создания геттеров, сеттеров и делетеров для атрибутов.
class MyClass:
def __init__(self, value):
self.hidden_value = value
@property
def value(self):
return self.hidden_value
@value.setter
def value(self, new_value):
self.hidden_value = new_value
obj = MyClass(10)
print(obj.value) # Вывод: 10
obj.value = 20
print(obj.value) # Вывод: 20
Это встроенные декораторы, их правильную работу обеспечивает сам интерпретатор Python.
6.4 Примеры использования декораторов
Логирование
Декораторы могут быть использованы для логирования вызовов функций и методов.
def log_call(func):
def wrapper(*args, **kwargs):
print(f"Вызов функции {func.__name__} с аргументами {args} и {kwargs}")
return func(*args, **kwargs)
return wrapper
@log_call
def add(x, y):
return x + y
print(add(2, 3))
Контроль доступа
Декораторы могут быть использованы для контроля доступа к функциям и методам.
def require_authentication(func):
def wrapper(*args, **kwargs):
if not args[0].is_authenticated:
raise PermissionError("Пользователь не аутентифицирован.")
return func(*args, **kwargs)
return wrapper
class User:
def __init__(self, is_authenticated):
self.is_authenticated = is_authenticated
@require_authentication
def view_profile(self):
print("Профиль пользователя")
user = User(is_authenticated=True)
user.view_profile() # Успешный вызов
user2 = User(is_authenticated=False)
user2.view_profile() # PermissionError: Пользователь не аутентифицирован.
Кэширование
Декораторы могут быть использованы для кэширования результатов функции.
def cache(func):
cached_results = {}
def wrapper(*args):
if args in cached_results:
return cached_results[args]
result = func(*args)
cached_results[args] = result
return result
return wrapper
@cache
def fib(n):
if n < 2:
return n
return fib(n - 1) + fib(n - 2)
print(fib(35))
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ