Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Способы использования и вызова декораторов в Python
Декораторы — это один из самых мощных и элегантных инструментов Python. Существует несколько способов вызвать/использовать декоратор, и понимание каждого из них критически важно для профессионального разработчика.
Способ 1: Простой декоратор без параметров
Это самый базовый способ применения декоратора к функции или методу:
def log_calls(func):
def wrapper(*args, **kwargs):
print(f"Вызов функции: {func.__name__}")
return func(*args, **kwargs)
return wrapper
@log_calls
def say_hello(name: str) -> str:
return f"Привет, {name}!"
print(say_hello("Alice"))
Это эквивалентно:
say_hello = log_calls(say_hello)
Способ 2: Декоратор с параметрами
Декоратор может принимать параметры:
def repeat(times: int):
def decorator(func):
def wrapper(*args, **kwargs):
results = []
for _ in range(times):
result = func(*args, **kwargs)
results.append(result)
return results
return wrapper
return decorator
@repeat(3)
def greet(name: str) -> str:
return f"Привет, {name}!"
Способ 3: Стекирование декораторов
Можно применять несколько декораторов:
def uppercase(func):
def wrapper(*args, **kwargs):
result = func(*args, **kwargs)
return result.upper()
return wrapper
def add_emoji(func):
def wrapper(*args, **kwargs):
result = func(*args, **kwargs)
return result + " EMOJI"
return wrapper
@add_emoji
@uppercase
def get_message() -> str:
return "привет мир"
Декораторы применяются снизу вверх!
Способ 4: Декоратор на методе класса
Декораторы работают с методами:
class Calculator:
@property
def value(self) -> int:
return self._value
Способ 5: Встроенные декораторы
Python предоставляет встроенные декораторы:
@property
class User:
def __init__(self, name: str):
self._name = name
@property
def name(self) -> str:
return self._name.title()
@staticmethod и @classmethod
class MathHelper:
multiplier = 10
@staticmethod
def add(a: int, b: int) -> int:
return a + b
@classmethod
def multiply(cls, x: int) -> int:
return x * cls.multiplier
Способ 6: Использование functools.wraps
В реальных проектах используйте functools.wraps:
import functools
from typing import Any, Callable
def log_calls(func: Callable) -> Callable:
@functools.wraps(func)
def wrapper(*args: Any, **kwargs: Any) -> Any:
print(f"Вызов: {func.__name__}")
return func(*args, **kwargs)
return wrapper
@log_calls
def divide(a: int, b: int) -> float:
return a / b
print(divide.__name__) # divide
Способ 7: Декоратор класса
Декораторы работают и с классами:
def add_repr(cls):
def __repr__(self):
attrs = ", ".join(f"{k}={v}" for k, v in self.__dict__.items())
return f"{cls.__name__}({attrs})"
cls.__repr__ = __repr__
return cls
@add_repr
class Person:
def __init__(self, name: str, age: int):
self.name = name
self.age = age
Способ 8: @dataclass
from dataclasses import dataclass
@dataclass
class Point:
x: float
y: float
point = Point(3.0, 4.0)
print(point.x) # 3.0
Способ 9: Декоратор как класс
Декоратор можно реализовать как класс:
class CountCalls:
def __init__(self, func: Callable):
self.func = func
self.count = 0
def __call__(self, *args: Any, **kwargs: Any) -> Any:
self.count += 1
print(f"Вызов {self.count}: {self.func.__name__}")
return self.func(*args, **kwargs)
@CountCalls
def hello(name: str) -> str:
return f"Привет, {name}!"
hello("Alice") # Вызов 1: hello
print(hello.count) # 1
Способ 10: Вручную вызвать декоратор
Можно применить декоратор без @ символа:
def original_function():
return "оригинал"
def func2():
return "func2"
func2 = log_calls(func2) # Ручное применение
func2() # Работает точно так же
Практический пример
import time
import functools
from typing import Any, Callable
def measure_time(func: Callable) -> Callable:
@functools.wraps(func)
def wrapper(*args: Any, **kwargs: Any) -> Any:
start = time.time()
result = func(*args, **kwargs)
elapsed = time.time() - start
print(f"{func.__name__} выполнена за {elapsed:.4f} сек")
return result
return wrapper
@measure_time
def slow_function():
time.sleep(0.5)
return "готово"
slow_function() # slow_function выполнена за 0.5001 сек
Сравнение способов
| Способ | Синтаксис | Параметры | Удобство |
|---|---|---|---|
| Простой | @decorator | Нет | 5 звёзд |
| С параметрами | @decorator(args) | Да | 4 звезды |
| Стекирование | @dec1 @dec2 | Да | 3 звезды |
| На методе | @decorator | Да | 5 звёзд |
| Встроенные | @property | Зависит | 5 звёзд |
| Класс-декоратор | @DecoratorClass | Да | 4 звезды |
Вывод
Декораторы в Python — это мощный инструмент для:
- Логирования и отладки
- Кеширования результатов
- Валидации аргументов
- Проверки прав доступа
- Трансформации результатов
- Профилирования производительности
Основное правило: используйте @ символ — это стандартный, читаемый способ применения декораторов в Python.