Decorator
A decorator in Python is a callable Python object that is used to modify a function, method or class definition. The original object, the one which is going to be modified, is passed to a decorator as an argument. The decorator returns a modified object, e.g. a modified function, which is bound to the name used in the definition.
Function Decorator
def func_decorator(func):
def wrapper(x):
if x == 0:
raise Exception('Denominator is zero ...');
return func(x);
return wrapper;
# before decoration
def inverse(x):
return 1.0/x
# after decoration
inverse = func_decorator(inverse)
try:
print(inverse(0.5))
print(inverse(0))
except Exception as e:
print(e)
def func_decorator(func):
def wrapper(x):
if x == 0:
raise Exception('Denominator is zero ...');
return func(x);
return wrapper;
@func_decorator
def inverse(x):
return 1.0/x;
try:
print(inverse(10))
print(inverse(0))
except Exception as e:
print(e)
def argument(func):
def wrapper(x):
if type(x) == int and x > 0:
return func(x)
else:
raise Exception("Argument is not an integer")
return wrapper
@argument
def factorial(n):
if n == 1:
return 1
else:
return n * factorial(n-1)
try:
print(factorial(10))
print(factorial(-1))
except Exception as e:
print(e)
# count the number of times a function has been called
def call_counter(func):
def helper(x):
helper.calls += 1 # set up a function attribute
return func(x)
helper.calls = 0
return helper
@call_counter
def succ(x):
return x + 1
print(succ.calls) # 0
for i in range(10):
print(succ(i))
print(succ.calls) # 10
Third-party Function Decoration
from math import sin, cos
def func_decorator(func):
def function_wrapper(x):
print('Decorating ...')
return func(x)
return function_wrapper
sin = func_decorator(sin)
print(sin(0))
from random import randint
def func_decorator(func):
def function_wrapper(*args, **kwargs):
return func(*args, **kwargs)
return function_wrapper
randint = func_decorator(randint)
print(randint(1, 10))
Decorators with Parameters
def dec_para(n):
def decorator(f):
def wrapper(a=10, b=100):
return f(a, b=b)*n
return wrapper
return decorator
@dec_para(10)
def f(a, b):
return a+b
print(f(1, 2)) # 30
Memoization
def memoize(f):
memo = {}
def helper(x):
if x not in memo:
memo[x] = f(x)
return memo[x]
return helper
@memoize
def fib(n):
if n == 0:
return 0
elif n == 1:
return 1
else:
return fib(n-1) + fib(n-2)
#fib = memoize(fib)
print(fib(40))
Callable Class
# callable class
class A:
def __init__(self):
print('Create an object ...')
def __call__(self, *args, **kwargs):
print('Arguments: ', args, kwargs)
a = A() # Create an object ...
print(callable(a)) # True
a(1, 2, b = 10, c = 20) # Arguments: (1, 2) {'b': 10, 'c': 20}
class Fibonacci:
def __init__(self):
self.cache = {}
def __call__(self, n):
if n not in self.cache:
if n == 0:
self.cache[0] = 0
elif n == 1:
self.cache[1] = 1
else:
self.cache[n] = self.__call__(n-1) + self.__call__(n-2)
return self.cache[n]
fib = Fibonacci()
for i in range(15):
print(fib(i), end=" ")
Class Decorator
class Decorator:
def __init__(self, func):
self.func = func
def __call__(self, x):
if x == 0:
raise Exception('Denominator is zero ...')
return self.func(x)
@Decorator
def inverse(x):
return 1.0/x;
try:
print(inverse(10))
print(inverse(0))
except Exception as e:
print(e)
Class Decorator with Parameters
class Decorator:
def __init__(self, func, n):
self.func = func
self.n = n
def __call__(self, x):
if x == 0:
raise Exception('Denominator is zero ...');
return self.n*self.func(x);
def inverse(x):
return 1.0/x;
inverse = Decorator(inverse, 10)
try:
print(inverse(10))
print(inverse(0))
except Exception as e:
print(e)
class Decorator:
def __init__(self, n):
self.n = n
def __call__(self, func):
def wrapper(x):
if x == 0:
raise Exception('Denominator is zero ...')
return self.n*func(x)
return wrapper
@Decorator(10)
def inverse(x):
return 1.0/x;
try:
print(inverse(10))
print(inverse(0))
except Exception as e:
print(e)
Reference