Декораторите в 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. Декоратори за Coroutines и Async функции

Асинхронните функции и съпрограмите също могат да бъдат декорирани, но декораторът също трябва да е асинхронен

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, за да разберете повече за това как демократизираме безплатното обучение по програмиране по света.