Выполнение функции декоратора Python

У меня есть демонстрационный код декоратора. Если я выполняю его без явного вызова функции greet, он выполняет инструкцию print внутри функции декоратора и выводит Inside decorator.

Я не могу понять это поведение декоратора. Как вызывается time_decorator, даже если я не вызывал функцию greet?

Я использую Python 3.

def time_decorator(original_func):
    print('Inside decorator')
    def wrapper(*args, **kwargs):
        start = time.clock()
        result = original_func(*args, **kwargs)
        end = time.clock()
        print('{0} is executed in {1}'.format(original_func.__name__, end-start))
        return result
    return wrapper


@time_decorator
def greet(name):
    return 'Hello {0}'.format(name)

Ответ 1

Декораторы вызывают время старт (когда интерпретатор python считывает код при запуске программы), а не время выполнения (когда фактически декорированная функция).

Во время выполнения это вызываемая функция wrapper, которая сама вызывает украшенную функцию и возвращает ее результат.

Итак, это абсолютно нормально, что выполняется строка print.

Если вы украшаете 10 функций, вы увидите в 10 раз больше результатов печати. Не нужно даже вызывать украшенные функции для этого.

Переместите print внутри wrapper, и этого больше не будет.

Decorators, а также metaclasses являются частью того, что называется мета-программированием (изменить/создать код из существующего кода). Это действительно увлекательный аспект программирования, который требует времени, чтобы понять, но предлагает потрясающие возможности.

Ответ 2

time_decorator выполняется во время выполнения функции. wrapper нет (эта функция вызывается, когда декорируется greet()).

@ - это просто синтаксический сахар. Следующие фрагменты кода эквивалентны.

Синтаксис декоратора:

@time_decorator
def greet(name):
    return 'Hello {0}'.format(name)

Явный процесс декорирования - декоратор - это функция, которая возвращает новую функцию на основе другой.

def greet(name):
    return 'Hello {0}'.format(name)

greet = time_decorator(greet)