Function decorators in python
26 Sep 2022
Function decorators are an elegant way of wrapping a function inside another function. I’m posting this here so I can always look it up but there’s good stuff on youTube too.
Suppose you want to do something every time a function is called, log it’s arguments and return value perhaps, or test how fast it runs, or cache it’s results. Decorators are your friends here.
# wrapper function
def log(fn):
def wrapper(*args, **kwargs):
print(fn)
out = fn(*args, **kwargs)
print("\tin: {}\n\tout: {}\n".format((*args,) + (kwargs,), out))
return out
return wrapper
# a different wrapper function
def timeThis(fn):
def wrapper(*args, **kwargs):
start = timer()
out = fn(*args, **kwargs)
end = timer()
print("execution took: {:0.8f} seconds".format(end - start))
return out
return wrapper
# 'decorate' the function with the name of the decorator
@log
def add(x, y=1):
return x+y
@timeThis
def sumOfSquaresUpTo(x):
return sum([x**2 for x in range(1,x+1)])
add(5, y=4)
sumOfSquaresUpTo(200)The key here is that the function you call, add for example, is actually fed into log first, log returns the wrapper function that calls add when it is itself called.