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