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

Что такое декораторы Python?

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

Понимание функций как объектов первого класса

Чтобы полностью понять декораторы, важно понимать, что функции — это первоклассные объекты в Python.
Это означает, что вы можете:

  1. Назначение функций переменным
  2. Передать функции в качестве аргументов другим функциям
  3. Функции возврата из других функций

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

Создание простого декоратора

Давайте создадим простой декоратор, который измеряет время, необходимое для выполнения функции.

import time

def timer_decorator(func):
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        print(f"{func.__name__} took {end_time - start_time:.2f} seconds to execute.")
        return result

    return wrapper

@timer_decorator
def slow_function():
    time.sleep(2)

slow_function()

В приведенном выше примере мы создаем декоратор с именем timer_decorator, который принимает функцию func в качестве аргумента. Декоратор возвращает новую функцию wrapper, которая измеряет время, затраченное на выполнение func, и печатает результат. Синтаксис @timer_decorator — это удобный способ применить декоратор к нашему slow_function.

Сцепление декораторов

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

def bold_decorator(func):
    def wrapper(*args, **kwargs):
        return f"<b>{func(*args, **kwargs)}</b>"
    return wrapper

def italic_decorator(func):
    def wrapper(*args, **kwargs):
        return f"<i>{func(*args, **kwargs)}</i>"
    return wrapper

@bold_decorator
@italic_decorator
def hello(name):
    return f"Hello, {name}!"

print(hello("Alice"))  # Output: <b><i>Hello, Alice!</i></b>

В приведенном выше примере мы объединяем два декоратора bold_decorator и italic_decorator, чтобы изменить поведение функции hello, добавляя теги HTML полужирный и курсивный к выходным данным.

Вот и все для этого урока!

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