#Python-Advance
#Python
Python Decorators
- It’s a very powerful and useful tool in Python
- It allows to
add functionality
to an existing function or class
.
def make_pretty(func):
def inner():
print("Inner function")
func()
return inner
# Without decorator
def ordinary():
print("Ordinary function")
pretty = make_pretty(ordinary)
pretty()
# With decorator(Using Closure)
@make_pretty
def ordinary():
print("Ordinary function")
ordinary()
# Inner function
# Ordinary function
def deco(func):
def inner_deco():
print("this is the start of my fun")
func()
print("this is the end of my fun")
return inner_deco
@deco
def test1():
print(4+5)
test1()
# this is the start of my fun
# 9
# this is the end of my fun
Nested Decorators
def decor1(func):
def inner():
x = func()
return x * x
return inner
def decor(func):
def inner():
x = func()
return 2 * x
return inner
@decor1
@decor
def num():
return 10
print(num())
# d1 = decor(num)
# d2 = decor1(d1)
# d2()
# Output: 400
Decorator without parameters
def outer(*args, **kwargs):
print("Outer")
def inner(func):
print("inner--", args[0])
func()
return inner
@outer('Amrit')
def my_func():
print("my function")
# -- fxn call not required
Decorator with parameters
def outer(func): # --
print("Outer")
def inner(*args, **kwargs): # --
print("inner--", args[0])
func(*args, **kwargs) # --
return inner
@outer
def my_func(var): # --
print("my function")
my_func("Amrit") # --
# Both has same Answer
Returning Values From Decorated Functions
import functools
def Outer(func):
@functools.wraps(func)
def inner(*args, **kwargs):
res = func(*args, **kwargs)
print("Inner")
return res
return inner
@Outer
def sum(a,b):
# print(a+b)
return a+b
print(sum(1,2))
Decorators With Arguments –> args, kwargs
# Divide by 0 -- Error
def Outer(fxn):
print("Outer")
def inner(*args, **kwargs):
if args[1] == 0:
# raise Exception("b cant be 0")
print("b can't be zero")
return
fxn(*args, **kwargs)
return inner
@Outer
def main(a, b):
print(a/b)
main(1,0)
# Calculate Execution time
# Using Decorator
# Also return value from fxn
import time
import functools
def Outer(func):
@functools.wraps(func)
def inner(*args, **kwargs):
start = time.time()
res = func(*args, **kwargs)
end = time.time()
print("Execution time: ", end-start)
return res
return inner
@Outer
def sum(a,b):
time.sleep(2)
# print(a+b)
return a+b
print(sum(1,2))
# Repeat N times
import functools
def repeat(num_times):
def decorator_repeat(func):
@functools.wraps(func)
def wrapper_repeat(*args, **kwargs):
for _ in range(num_times):
func(*args, **kwargs)
# value = func(*args, **kwargs)
# return value
return wrapper_repeat
return decorator_repeat
@repeat(num_times=4)
def greet(name):
print(f"Hello {name}")
greet("Amrit-")
Reference