We will discuss about the decorators in Python in this blog. A decorator is a function that takes another function as an argument, and it returns a function with enhanced functionality. You might have seen @staticmethod, @classmethod, and @property in your Python project code, all are example of decorators. We will discuss first requirements and then will discuss @staticmethod, @classmethod, and @property decorators with example and code.The things that we should know before decorators
Everything in Python is an object:
def book(name="Atomic Habits"): return f"self-help book: {name}" print(book()) # Output: self-help book: Atomic Habits book_description = book print(book_description()) # Output: self-help book: Atomic Habits
Defining functions within functions:
def book(name="Atomic Habits"): print("You are in the book() function") def self_help_book(): return f"You are in the self_help_book() function." def algorithm_book(): return f"You are in the algorithm_book() function." print(self_help_book()) print(algorithm_book()) print("You are in the book() function") book() # Output: You are in the book() function # You are in the self_help_book() function. # You are in the algorithm_book() function. # You are in the book() function
Returning functions from within functions:
def book(name="Atomic Habits"): print (f"{name} books is a really good book") def book_zoner(): return (f"{name}: is a self help book.") return book_zoner a = book() print(a) # Output: Atomic Habits books is a really good book #
.book_zoner at 0x105044400> Giving a function as an argument to another function
def book(): print("Atomic Habits is a very good book.") def gener_of_book(function): print("Atomic habits book is self help book") function() print("After calling argument passed function") gener_of_book(book) # Output # Atomic habits book is self help book # Atomic Habits is a very good book. # After calling argument passed function
Above logic is used in a decorator. The decorator adds or modifies the functionality of the existing.
Writing your first decorator
def make_new_decorator(function): def wrapTheFunction(): print("I am doing great work in the field of AI") function() print("I am doing great work in the field of AI") return wrapTheFunction def book_review(): print("Cracking the coding interview Book by Gayle Laakmann McDowell is very good book for DSA") book_review() # Outputs: "Cracking the coding interview Book by Gayle Laakmann McDowell is very good book for DSA" a_function_requiring_decoration = make_new_decorator(book_review) # now a_function_requiring_decoration is wrapped by wrapTheFunction() a_function_requiring_decoration() # Outputs: I am doing great work in the field of AI # Cracking the coding interview Book by Gayle Laakmann McDowell is very good book for DSA # I am doing great work in the field of AI
def make_new_decorator(function): def wrapTheFunction(): print("I am doing the greate work in the field of AI") function() print("I am doing the greate work in the field of AI") return wrapTheFunction @make_new_decorator def book_review(): print("Cracking the coding interview Book by Gayle Laakmann McDowell is very good book for DSA") book_review() # Outputs: I am doing the greate work in the field of AI # Cracking the coding interview Book by Gayle Laakmann McDowell is very good book for DSA # I am doing the greate work in the field of AI
Syntax of Decorator Parameters
def decorator_name(func): def wrapper(*args, **kwargs): # Add functionality before the original function call result = func(*args, **kwargs) # Add functionality after the original function call return result return wrapper @decorator_name def function_to_decorate(): # Original function code pass
Common Built-in Decorators in Python
1. @staticmethod 2. @classmethod 3. @property@staticmethod
staticmethod decorator is used to define a method that does not operate in the instance of the class. It is called by the class itself, not by the instance of the classclass RecatangleArea: def __init_(self, height, width): self.height = height self.width = width def calculate_area_1(self): area = self.height*self.width return area @staticmethod def calculate_area_2(height, width): area = height*width return area area = RecatangleArea.calculate_area_2(5,4) print(area) # You will get error when you run RecatangleArea.calculate_area_1(5,4) because calculate_area_1 require class instance area = RecatangleArea.calculate_area_1(5,4) print(area)
@classmethod
class RealState: property_price = 2 # price in crore @classmethod def price_of_new_house(cls, price): cls.property_price = price return cls.property_price print(RealState.property_price) # Output: 2 RealState.price_of_new_house(5) print(RealState.property_price) # Output: 5 real_state_object = RealState() print(real_state_object.property_price) # Output: 5
@property
class RecatangleArea: def __init__(self, h, w): self.rectanle_height = h self.rectanle_width = w @property def height(self): return self.rectanle_height @height.setter def height(self, h): self.rectanle_height = h @property def width(self): return self.rectanle_width @width.setter def width(self, w): self.rectanle_width = w def area(self): return self.rectanle_height*self.rectanle_width area_object = RecatangleArea(5,4) print(f"Height: {area_object.height}") print(f"Width: {area_object.width}") print(f"Area of the rectangle: {area_object.area()}") # Output: # Height: 5 # Width: 4 # Area of the rectangle: 20 area_object.height = 10 area_object.width = 8 print(f"Height: {area_object.height}") print(f"Width: {area_object.width}") print(f"Area of the rectangle: {area_object.area()}") # Output: # Height: 10 # Width: 8 # Area of the rectangle: 80
Sources 1. Python Bultin decorators List 2. Decorators in Python 3. Decorators