What are Decorators #
A decorator is a callable that takes another function as argument and returns a new function as output. It’s used in the following way:
@logthis
def perform_action(n):
....
....Decorators come under Metaprogramming i.e changing program behaviour at runtime.
Example #
Decorators are executed right after the decorated function is defined. That is usually at import time. The following decorator is used to find the execution time of a function
import time
from functools import wraps
def timeit(func):
"""
Reports the execution time
"""
@wraps(func)
def wrapper(*args,**kwargs):
start = time.time()
result = func(*args,**kwargs)
end = time.time()
print(func__name__,end - start)
return result
return wrapperExample of using this decorator
@timeit
def exponentiation(b,n):
exp_iter(b, n, 1)
def exp_iter(b,counter,product):
if counter == 0:
print(product)
else:
counter = counter - 1
product = b * product
exp_iter(b,counter,product)and the output will be
16
exponentiation 0.00020766258239746094The use of wraps(func)in the above code is there to preserve function metadata.This will help us in getting function metadata like:
exponentiation.__name__
exponentiation.__doc__Defining a decorator that takes arguments #
You can also define decorators that can accept arguments.For example let us take a decorator that adds logging to a function and allows the user to specify the loggin details:
from functools import wraps
import logging
def logger(level,name=None,message=None):
"""
A simple logger decorator that allows the
user to specify the logging details like
name and message
"""
def decorate(func):
logname = name if name else func.__module__
log = logging.getlogger(logname)
logmessage = message if message else func.__name__
@wraps(func)
def wrapper(*args,**kwargs):
log.log(level,logmsg)
return func(*args,**kwargs)
return wrapper
return decorate Usage:
@logged(logging.DEBUG)
def add(x,y):
return x + yDecorators are definately an useful functionality.There are some advance decorator concepts that I will write about next, these are:
- Defining decorators inside classes
- Defining decorators as classes