This is a generalised version of: decorator-once-per-minute
@once_per_n(5) # for every 5 mins
def add(a, b):
return a + b
# Which means...
add = once_per_n(5)(add)
# ^~~~~~~~~~~~^ this should return a function
How would you implement that? -> 3 levels of functions.
# Executes once, when we get an argument
def once_per_n(n):
# Executes once, when we decorate the function
def middle(func): # <--- This is the decorated function, accepts no args
last_invoked = 0
# Executes every time we invoke the function
def wrapper(*args, **kargs):
nonlocal last_invoked
if time.time() - last_invoked < n:
raise ...
last_invoked = time.time()
return fun(*args, **kargs)
return wrapper
return middle