Постоянство значения переменной в области действия функции декоратора в python - PullRequest
2 голосов
/ 17 марта 2020

Слушая PyCon 2019 Реувена М. Лернера , говорим о декораторах и натолкнулся на следующий пример функции декорирования.

import time

def once_per_minute(func):
    """A decorator that prevents the decorated func 
    from being invoked more than once per minute"""

    last_invoked = 0

    def wrapper(*args, **kwargs):
        nonlocal last_invoked

        elapsed_time = time.time() - last_invoked

        if elapsed_time < 60:

            raise Exception(f"Only {elapsed_time} has passed")

        last_invoked = time.time()

        return func(*args, **kwargs)

    return wrapper

Что вызвало у меня замешательство, почему значение last_invoked сохраняется при каждом запуске декорированной функции? Я предполагаю, что при каждом запуске декорированной функции будет вызываться декоратор. И каждый раз, когда вызывается декоратор, last_invoked следует сбрасывать в ноль.

Я заглянул в документацию по ключевому слову nonlocal, и, похоже, это указывает на то, что это переменная, связанная в ближайшей области видимости. Это все еще не объясняет, почему last_invoked может успешно отслеживать прошедшее время.

...