Как работает в данном примере декорирование?

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

Чтобы более полно понять, как работает декорирование, рассмотрим пример:

def decorator_function(original_function):
    def wrapper_function(*args, **kwargs):
        print("Дополнительный код, который выполняется перед вызовом оригинальной функции.")
        result = original_function(*args, **kwargs)
        print("Дополнительный код, который выполняется после вызова оригинальной функции.")
        return result
    return wrapper_function

@decorator_function
def original_function():
    print("Оригинальная функция.")

original_function()

В этом примере мы определяем декораторную функцию decorator_function, которая принимает оригинальную функцию original_function в качестве аргумента. Внутри декораторной функции мы определяем вложенную функцию wrapper_function, которая содержит дополнительный код, выполняющийся перед и после вызова оригинальной функции. Мы возвращаем wrapper_function, чтобы использовать ее в качестве декоратора.

Затем мы используем декоратор @decorator_function перед определением original_function. Это эквивалентно вызову original_function = decorator_function(original_function), то есть декоратор применяется к original_function и переопределяет ее новой функцией, которая включает дополнительный код.

При вызове original_function() происходит следующий процесс:
1. Дополнительный код wrapper_function перед вызовом оригинальной функции выводится на экран.
2. Вызывается оригинальная функция original_function, которая выводит "Оригинальная функция" на экран.
3. Дополнительный код wrapper_function после вызова оригинальной функции выводится на экран.

Таким образом, декорирование позволяет добавлять дополнительный функционал к существующей функции без необходимости изменения ее исходного кода. Это может быть полезно, например, для реализации логирования, проверки аргументов или измерения времени выполнения функции.