Decorators in Python
Understanding about a function that takes an other function as an argument and adds further functonallity.
def decorator_function(original_function):
def wrapper_function():
return original_function()
return wrapper_function
def display():
print("Display Function Executed")
decorated_display = decorator_function(display)
decorated_display()
def decorator_function(original_function):
def wrapper_function():
print("Wrapper Executed this before {}".format(original_function.__name__))
return original_function()
return wrapper_function
def display():
print("Display Function Executed")
decorated_display = decorator_function(display)
decorated_display()
def decorator_function(original_function):
def wrapper_function(*args, **kwargs):
print("Wrapper Executed this before {}".format(original_function.__name__))
return original_function(*args, **kwargs)
return wrapper_function
@decorator_function
def display():
print("Display Function Executed")
display()
@decorator_function
def display_info(name, age):
print("Display_info executed with arguments: ({}, {})".format(name, age))
display_info("John", 25)
decorated_display = decorator_function(display)
decorated_display()
is similar to
@decorator_function
def display():
print("Display Function Executed")
# the above representation exactly says:
display = decorator_functon(display)
class decorator_class(object):
def __init__(self, original_function):
self.original_function = original_function
def __call__(self, *args, **kwargs):
print("Call method executed before {}".format(self.original_function.__name__))
return self.original_function(*args, **kwargs)
@decorator_class
def display():
print("Display Function Executed")
display()
@decorator_class
def display_info(name, age):
print("Display_info executed with arguments: ({}, {})".format(name, age))
display_info("John", 25)
def my_logger(orig_func):
import logging
logging.basicConfig(filename='{}.log'.format(orig_func.__name__,
level= logging.INFO))
def wrapper(*args, **kwargs):
logging.info(
'Ran with Args: {}, and Kwargs {}'.format(args, kwargs))
return wrapper
@my_logger
def display_info(name, age):
print("Display_info executed with arguments: ({}, {})".format(name, age))
display_info("Oill", 45)
def my_timer(orig_func):
import time
def wrapper(*args, **kwargs):
t1 = time.time()
result = orig_func(*args, **kwargs)
t2 = time.time() - t1
print('{} ran in: {} sec'.format(orig_func.__name__, t2))
return result
return wrapper
@my_timer
def display_info(name, age):
print("Display_info executed with arguments: ({}, {})".format(name, age))
display_info("Kill", 15)
@my_logger
@my_timer
def display_info(name, age):
print("Display_info executed with arguments: ({}, {})".format(name, age))
# adds the result in the log file
display_info(2, 4)
@my_timer
@my_logger
def display_info(name, age):
print("Display_info executed with arguments: ({}, {})".format(name, age))
display_info()
The is an issue running up with the sequence or order of placing decorators.
# Decorators
from functools import wraps
def my_logger(orig_func):
import logging
logging.basicConfig(filename='{}.log'.format(orig_func.__name__), level=logging.INFO)
@wraps(orig_func)
def wrapper(*args, **kwargs):
logging.info(
'Ran with args: {}, and kwargs: {}'.format(args, kwargs))
return orig_func(*args, **kwargs)
return wrapper
def my_timer(orig_func):
import time
@wraps(orig_func)
def wrapper(*args, **kwargs):
t1 = time.time()
result = orig_func(*args, **kwargs)
t2 = time.time() - t1
print('{} ran in: {} sec'.format(orig_func.__name__, t2))
return result
return wrapper
import time
@my_logger
@my_timer
def display_info(name, age):
time.sleep(1)
print('display_info ran with arguments ({}, {})'.format(name, age))
display_info('Tom', 22)