5/13/2020

Python - Decorators - Dynamically Alter The Functionality Of Your Functions

** Decorators - Dynamically Alter The Functionality Of Your Functions


==========================================

def outer_function():
message = 'Hi'

def inner_function():
print(message)

return inner_function()

outer_function()

---------------------------------

Hi

---------------------------------

==========================================

# Decorators

def outer_function():
message = 'Hi'

def inner_function():
print(message)

return inner_function

outer_function()

---------------------------------

nothing

---------------------------------

==========================================

def outer_function():
message = 'Hi'

def inner_function():
print(message)

return inner_function

my_func = outer_function()
my_func()
my_func()
my_func()

---------------------------------

Hi
Hi
Hi

---------------------------------

==========================================

def outer_function(msg):
message = msg

def inner_function():
print(message)

return inner_function

hi_func = outer_function('Hi')
bye_func = outer_function('Bye')

hi_func()
bye_func()

---------------------------------

Hi
Bye

---------------------------------

==========================================

def outer_function(msg):
def inner_function():
print(msg)

return inner_function

hi_func = outer_function('Hi')
bye_func = outer_function('Bye')

hi_func()
bye_func()

---------------------------------

Hi
Bye

---------------------------------

==========================================

def decorator_function(original_function):
def wrapper_function():
return original_function()
return wrapper_function


def display():
print('display function ran')

decorated_display = decorator_function(display)

decorated_display()

---------------------------------

display function ran

---------------------------------

==========================================

def decorator_function(original_function):
def wrapper_function():
print('wrapper executed this befor'.format(original_function.__name__))
return original_function()
return wrapper_function


def display():
print('display function ran')

decorated_display = decorator_function(display)

decorated_display()


---------------------------------

wrapper executed this befor
display function ran

---------------------------------

==========================================

def decorator_function(original_function):
def wrapper_function():
print('wrapper executed this befor'.format(original_function.__name__))
return original_function()
return wrapper_function


@decorator_function
def display():
print('display function ran')

display()

---------------------------------

wrapper executed this befor
display function ran

---------------------------------

==========================================

def decorator_function(original_function):
def wrapper_function():
print('wrapper executed this befor'.format(original_function.__name__))
return original_function()
return wrapper_function


@decorator_function
def display():
print('display function ran')


def display_info(name, age):
print('display_info ran with arguments ({}, {})'.format(name, age))

display_info('John', 25)

---------------------------------

display_info ran with arguments (John, 25)

---------------------------------

==========================================

def decorator_function(original_function):
def wrapper_function():
print('wrapper executed this befor'.format(original_function.__name__))
return original_function()
return wrapper_function


@decorator_function
def display():
print('display function ran')

@decorator_function
def display_info(name, age):
print('display_info ran with arguments ({}, {})'.format(name, age))

display_info('John', 25)

---------------------------------

display_info('John', 25)
TypeError: wrapper_function() takes 0 positional arguments but 2 were given

---------------------------------

==========================================

def decorator_function(original_function):
def wrapper_function(*args, **kwargs):
print('wrapper executed this befor'.format(original_function.__name__))
return original_function(*args, **kwargs)
return wrapper_function


@decorator_function
def display():
print('display function ran')

@decorator_function
def display_info(name, age):
print('display_info ran with arguments ({}, {})'.format(name, age))

display_info('John', 25)

display()

---------------------------------

wrapper executed this befor
display_info ran with arguments (John, 25)
wrapper executed this befor
display function ran

---------------------------------

==========================================

def decorator_function(original_function):
def wrapper_function(*args, **kwargs):
print('wrapper executed this befor'.format(original_function.__name__))
return original_function(*args, **kwargs)
return wrapper_function


class decorator_class(object):
def __init__(self, original_function):
self.original_function = original_function

def __call__(self, *args, **kwargs):
print('call method executed this before {}'.format(self.original_function.__name__))
return self.original_function(*args, **kwargs)


@decorator_class
def display():
print('display function ran')

@decorator_class
def display_info(name, age):
print('display_info ran with arguments ({}, {})'.format(name, age))

display_info('John', 25)

display()

---------------------------------

call method executed this before display_info
display_info ran with arguments (John, 25)
call method executed this before display
display function ran

---------------------------------

==========================================

def decorator_function(original_function):
def wrapper_function(*args, **kwargs):
print('wrapper executed this befor'.format(original_function.__name__))
return original_function(*args, **kwargs)
return wrapper_function



@decorator_function
def display():
print('display function ran')

@decorator_function
def display_info(name, age):
print('display_info ran with arguments ({}, {})'.format(name, age))

display_info('John', 25)

display()

---------------------------------

wrapper executed this befor
display_info ran with arguments (John, 25)
wrapper executed this befor
display function ran

---------------------------------

==========================================

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 orig_func(*args, **kwargs)

return wrapper


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_logger
def display_info(name, age):
print('display_info ran with arguments ({}, {})'.format(name, age))

display_info('John', 25)


---------------------------------

display_info ran with arguments (John, 25)


-------display_info.log---------------

INFO:root:Ran with args: ('John', 25), and kwargs: {}

---------------------------------

==========================================

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 orig_func(*args, **kwargs)

return wrapper


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_logger
def display_info(name, age):
print('display_info ran with arguments ({}, {})'.format(name, age))

display_info('Hank', 30)

---------------------------------

display_info ran with arguments (Hank, 30)


-------display_info.log---------------

INFO:root:Ran with args: ('John', 25), and kwargs: {}
INFO:root:Ran with args: ('Hank', 30), and kwargs: {}

---------------------------------

==========================================

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 orig_func(*args, **kwargs)

return wrapper


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


import time

@my_timer
def display_info(name, age):
time.sleep(1)
print('display_info ran with arguments ({}, {})'.format(name, age))

display_info('Hank', 30)


---------------------------------

display_info ran with arguments (Hank, 30)
display_info ran in: 1.0000507831573486 sec

---------------------------------

==========================================

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 orig_func(*args, **kwargs)

return wrapper


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


import time

@my_timer
@my_logger
def display_info(name, age):
time.sleep(1)
print('display_info ran with arguments ({}, {})'.format(name, age))

display_info('Hank', 30)

---------------------------------

display_info ran with arguments (Hank, 30)
wrapper ran in: 1.0000500679016113 sec

-------display_info.log---------------

INFO:root:Ran with args: ('John', 25), and kwargs: {}
INFO:root:Ran with args: ('Hank', 30), and kwargs: {}
INFO:root:Ran with args: ('Hank', 30), and kwargs: {}

---------------------------------


==========================================

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 orig_func(*args, **kwargs)

return wrapper


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


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('Hank', 30)

---------------------------------

display_info ran with arguments (Hank, 30)
display_info ran in: 1.0030512809753418 sec

---------wrapper.log----------------

INFO:root:Ran with args: ('Hank', 30), and kwargs: {}

---------------------------------

==========================================

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 orig_func(*args, **kwargs)

return wrapper


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


import time

def display_info(name, age):
time.sleep(1)
print('display_info ran with arguments ({}, {})'.format(name, age))

display_info = my_logger(my_timer(display_info))

print(display_info.__name__)

---------------------------------

wrapper

---------------------------------

==========================================

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_timer
@my_logger
def display_info(name, age):
time.sleep(1)
print('display_info ran with arguments ({}, {})'.format(name, age))

display_info = my_timer(display_info)

print(display_info.__name__)

display_info('Hank', 30)

---------------------------------

display_info
display_info ran with arguments (Hank, 30)
display_info ran in: 1.000056505203247 sec
display_info ran in: 1.000056505203247 sec

---------------------------------

==========================================


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_timer
@my_logger
def display_info(name, age):
time.sleep(1)
print('display_info ran with arguments ({}, {})'.format(name, age))

display_info('Tom', 22)

---------------------------------

display_info ran with arguments (Tom, 22)
display_info ran in: 1.001056432723999 sec

-------display_info.log---------------

INFO:root:Ran with args: ('Tom', 22), and kwargs: {}

---------------------------------