Слушая 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
может успешно отслеживать прошедшее время.