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

Хотя базовое использование декораторов является обычным явлением, расширенные конструкции могут помочь решить более сложные проблемы. В этой статье мы рассмотрим некоторые продвинутые шаблоны и методы, связанные с декораторами в Python.

1. Декораторы с аргументами

В отличие от простых декораторов, эти декораторы принимают дополнительные аргументы, обеспечивая более гибкое и специфическое поведение.

def decorator_with_args(arg1, arg2):
    def actual_decorator(func):
        def wrapper(*args, **kwargs):
            print(f"Decorator argument values: {arg1}, {arg2}")
            return func(*args, **kwargs)
        return wrapper
    return actual_decorator

@decorator_with_args("hello", "world")
def greet(name):
    print(f"Hi, {name}")

greet("Alice")

2. Декораторы, поддерживающие метаданные

Оформленные функции могут потерять свои метаданные. Функцию functools.wraps можно использовать, чтобы гарантировать, что метаданные исходной функции останутся нетронутыми.

import functools

def simple_decorator(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        return func(*args, **kwargs)
    return wrapper

3. Цепочка декораторов

Декораторы можно применять последовательно, каждое здание поверх предыдущего. Порядок имеет значение и может изменить конечный результат.

def decorator_1(func):
    def wrapper(*args, **kwargs):
        print("Decorator 1")
        return func(*args, **kwargs)
    return wrapper

def decorator_2(func):
    def wrapper(*args, **kwargs):
        print("Decorator 2")
        return func(*args, **kwargs)
    return wrapper

@decorator_1
@decorator_2
def say_hello():
    print("Hello!")

say_hello()

4. Декораторы на основе классов

Вместо использования функций декораторы можно разрабатывать с использованием классов, предлагая больше структуры и возможностей ООП (например, сохранение состояния).

class ClassDecorator:
    def __init__(self, func):
        self.func = func

    def __call__(self, *args, **kwargs):
        print("Before the function call")
        result = self.func(*args, **kwargs)
        print("After the function call")
        return result

@ClassDecorator
def greet(name):
    print(f"Hi, {name}")

greet("Bob")

5. Декораторы для сопрограмм и асинхронных функций

Асинхронные функции и сопрограммы также можно декорировать, но декоратор также должен быть асинхронным.

import asyncio

def async_decorator(coro):
    async def wrapper(*args, **kwargs):
        print("Before the coroutine")
        await asyncio.sleep(1)
        result = await coro(*args, **kwargs)
        print("After the coroutine")
        return result
    return wrapper

@async_decorator
async def async_greet():
    print("Hello asynchronously!")

asyncio.run(async_greet())

6. Параметризованные декораторы для классов

Эти декораторы принимают аргументы и могут применяться к классам, влияя на работу класса или его методов.

def class_decorator(arg1, arg2):
    def inner_decorator(cls):
        class NewClass(cls):
            attribute1 = arg1
            attribute2 = arg2
        return NewClass
    return inner_decorator

@class_decorator("value1", "value2")
class MyClass:
    pass

obj = MyClass()
print(obj.attribute1, obj.attribute2)

Заключение

Декораторы в Python, хотя и кажутся простыми, предлагают глубину дизайнерских возможностей. Они позволяют разработчикам писать чистый, СУХОЙ (не повторяйте себя) и пригодный для повторного использования код. Расширенные шаблоны, подобные рассмотренным в этой статье, открывают еще больший потенциал, позволяя вносить мощные модификации и улучшения в функции и поведение методов. Как и в случае с любым другим инструментом, очень важно разумно использовать декораторы, чтобы гарантировать, что код остается читабельным и поддерживаемым.

Спасибо, что дочитали до конца. Пожалуйста, подумайте о том, чтобы подписаться на автора и эту публикацию. Посетите Stackademic, чтобы узнать больше о том, как мы демократизируем бесплатное образование в области программирования во всем мире.