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

Как запустить декоратор не через @?

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

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

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

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

Декораторы в Python: традиционный способ вызова

Декератор — это функция, которая модифицирует поведение другой функции или класса. Обычно декораторы применяют через символ @, но Python позволяет применять их явно, вызывая как обычные функции.

Основной принцип

Когда вы пишите:

@decorator
def func():
    pass

Пython интерпретирует это как:

def func():
    pass
func = decorator(func)

Синтаксис @ — это просто сахар. Вы можете применить декоратор напрямую, вызвав функцию:

def my_decorator(func):
    def wrapper():
        print("До вызова функции")
        result = func()
        print("После вызова функции")
        return result
    return wrapper

def greet():
    print("Привет, мир!")

# Применение декоратора без @
greet = my_decorator(greet)
greet()

Вывод:

До вызова функции
Привет, мир!
После вызова функции

Применение к функциям с аргументами

def log_decorator(func):
    def wrapper(*args, **kwargs):
        print(f"Вызов функции {func.__name__} с аргументами {args} {kwargs}")
        return func(*args, **kwargs)
    return wrapper

def add(a, b):
    return a + b

# Явное применение декоратора
add = log_decorator(add)
result = add(5, 3)  # Выведет: Вызов функции add с аргументами (5, 3) {}
print(result)       # 8

Применение нескольких декораторов

Без символа @ применяют порядок "слева направо":

def decorator_a(func):
    def wrapper():
        print("A до")
        func()
        print("A после")
    return wrapper

def decorator_b(func):
    def wrapper():
        print("B до")
        func()
        print("B после")
    return wrapper

def greet():
    print("Привет!")

# Эквивалент @decorator_a @decorator_b greet
greet = decorator_a(decorator_b(greet))
greet()

Вывод:

A до
B до
Привет!
B после
A после

Применение к классам

def singleton(cls):
    instances = {}
    def get_instance(*args, **kwargs):
        if cls not in instances:
            instances[cls] = cls(*args, **kwargs)
        return instances[cls]
    return get_instance

class Database:
    def __init__(self):
        self.connection = "connected"

# Явное применение декоратора к классу
Database = singleton(Database)

db1 = Database()
db2 = Database()
print(db1 is db2)  # True, один и тот же объект

Когда это полезно

Динамическое применение: Если вам нужно решить в runtime, применять ли декоратор.

def timing_decorator(func):
    import time
    def wrapper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        print(f"Выполнено за {time.time() - start:.4f} сек")
        return result
    return wrapper

def slow_function():
    import time
    time.sleep(0.5)
    print("Функция завершена")

should_time = True
if should_time:
    slow_function = timing_decorator(slow_function)

slow_function()

Вывод

Декораторы в Python — это функции высшего порядка. Символ @ просто оборачивает функцию в другую функцию. Явный вызов func = decorator(func) даёт полный контроль над тем, когда и как применять модификации.

Как запустить декоратор не через @? | PrepBro