The Power of Python Decorators

  1. Function as “First Class Objects”
def print_first(name):
print(f"{name} is my favorite language")


def print_second(name):
print(f"{name} is easy to learn")


def print_func(func_name):
return func_name("Python")

print_func(print_first)
print_func(print_second)
def favorite_lang():
print("Favorite language function")

def print_python():
print("Python is my favorite language")

def print_java():
print("Java is my favorite language")

print_python()
print_java()

favorite_lang()
def favorite_lang(key):

def print_python():
return "Python is my favorite language"

def print_java():
return "Java is my favorite language"

if key == 1:
return print_python
else:
return print_java

lang1 = favorite_lang(1)
lang2 = favorite_lang(2)

print(lang1)
print(lang1())

print(lang2)
print(lang2())

Simple or Basic Decorators

Let’s understand with example by defining decorator function

def decorator_function(func):
def wrapper_function():
print("Function Execution starts here")
func()
print("Function Execution ends here")
return wrapper_function
def execute_func():
print("Executing Function ......")

execute_func = decorator_function(execute_func)

execute_func()
@decorator_function
def execute_func():
print("Executing Function ......")

execute_func()
def decorator_function(func):
@functools.wraps(func)
def wrapper_function(*args, **kwargs):
print("Function Execution starts here")
func(*args, **kwargs)
print("Function Execution ends here")
return func(*args, **kwargs)
return wrapper_function

Advance Decorators

Now we are bit comfortable with simple decorators. Lets us know understand the some Advance decorators.

  1. Decorator with classes
from decorators import debug, timer

class Place:
@debug
def __init__(self, max_rate):
self.max_rate= max_rate
self.rating = None
@timer
def rating(self, rating):
sleep(1000)
self.rating = rating
place = Place(5)
Calling __init__(<place.Place object at 0x7efccce059608>, 5)
'__init__' returned None


place.rating(3)
Finished 'rating' in 0.43876 secs
from decorators import debug, timer
@timer
class Place:
def __init__(self, max_rate):
self.max_rate= max_rate
self.rating = None
def rating(self, rating):
sleep(1000)
self.rating = rating2.
place = Place(5)
from decorators import debug, timer

@debug
@timer
def display(name):
print("Hello World!")
from decorators import debug, timer

@timer
@debug
def display(name):
print("Hello World!")
@repeat(num_times=10)
def display(name):
print("Hello World!")
import functools

class FuncCountCalls:
def __init__(self, func):
functools.update_wrapper(self, func)
self.func = func
self.count_calls = 0

def __call__(self, *args, **kwargs):
self.count_calls += 1
print(f"Calling {self.func.__name__}")
print(f"Call count : {self.count_calls}")
return self.func(*args, **kwargs)

@FuncCountCalls
def check_count():
print("Hello World!")

check_count()
check_count()
from functools import update_wrapper


class Tally:
def __init__(self, func):
update_wrapper(self, func)
self.func = func
self.tally = {}
self.n_calls = 0

def __call__(self, *args, **kwargs):
self.n_calls += 1
self.tally[self.func.__name__] = self.n_calls

print("Callable Tally:", self.tally)
return self.func(*args, **kwargs)


@Tally
def hello(name):
return f"Hello {name}!"


print(hello("Redowan"))
print(hello("Nafi"))

Conclusion

In this blog we explored the beauty of Python decorators by understanding the simple decorators to advance decorators. In larger projects especially, decorators give us much more flexibility to encapsulate various operations without exposing the irrelevant APIs to other modules.

References

  1. https://book.pythontips.com/en/latest/decorators.html
  2. https://www.python.org/dev/peps/pep-0318/
  3. https://dbader.org/blog/python-decorators

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Chandra Shekhar Sahoo

Chandra Shekhar Sahoo

5 Followers

Freelancers, Python Developer by Profession and ML Enthusiasts