← Назад к вопросам

Какие знаешь способы вызвать декоратор?

2.0 Middle🔥 131 комментариев
#Python Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Способы использования и вызова декораторов в 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.

Какие знаешь способы вызвать декоратор? | PrepBro