Decorators: Adding Toppings to Your Python Code
Swarooprani Manoor
Mentored 2K+ Students | 20 Years of Experience in Education & Mentorship | Passionate About Python Coding
Hello Pythonistas!
Welcome back to another exciting edition of Python Programming!
In today's article, we're discussing one of the interesting concepts of Python, decorators.
Imagine you're a master ice cream maker. Your ice creams are so delicious that they're a hit with everyone. Now, let's say you want to take things up a notch by adding three special toppings: chocolate sprinkles, strawberry chunks, and mango bites. But here's the twist – you don't want to change the amazing taste of your basic ice cream.
And that's where decorators step in. You see, you won't be altering the way you make your basic ice cream. The same wonderful ingredients and process will be used for your regular ice cream. Instead, you'll whip up three separate decorating ingredients: chocolate chips, mango bites, and strawberry chunks. Then, you'll either use them individually or wrap them around your basic ice cream to create something extraordinary.
So, get ready to learn about decorators – your secret tool for adding that extra sparkle to your Python code!
Let's start by defining a simple function basic_ice_cream that represents our basic ice cream.
def basic_ice_cream():
? ? return "Basic ice cream"
2. Defining the Decorator:
def add_toppings(func):
? ? def wrapper():
? ? ? ? return func() + " with toppings"
? ? return wrapper
The add_toppings decorator takes a function func as an argument and defines an inner wrapper function. The wrapper function adds " with toppings" to the result of the decorated function.
3. Applying the Decorator:
@add_toppings
def chocolate_ice_cream():
? ? return "Chocolate ice cream"
@add_toppings
def strawberry_ice_cream():
? ? return "Strawberry ice cream"
@add_toppings
def mango_ice_cream():
? ? return "Mango ice cream"
We apply the add_toppings decorator to the chocolate_ice_cream, strawberry_ice_cream, and mango_ice_cream functions using the @ syntax. This means that calling these functions will now automatically include the toppings.
4. Calling the Decorated Functions:
result_basic = basic_ice_cream()
result_chocolate = chocolate_ice_cream()
result_strawberry = strawberry_ice_cream()
result_mango = mango_ice_cream()
We call each of the functions to get the results. Note that basic_ice_cream is not decorated, so it returns the basic ice cream without toppings.
5.Printing the Results:
print(result_basic)
print(result_chocolate)
print(result_strawberry)
print(result_mango)
Finally, we print the results of calling each function. You'll notice that the decorated functions (chocolate_ice_cream, strawberry_ice_cream, and mango_ice_cream) automatically include the " with toppings" text due to the decorator.
Complete Code:
领英推荐
# Define the basic ice cream function
def basic_ice_cream():
? ? return "Basic ice cream"
# Define the decorator
def add_toppings(ice_cream_func):
? ? def wrapper():
? ? ? ? result = ice_cream_func()
? ? ? ? result += " with toppings"
? ? ? ? return result
? ? return wrapper
# Apply the decorator to specific ice cream functions
@add_toppings
def chocolate_ice_cream():
? ? return "Chocolate ice cream"
@add_toppings
def strawberry_ice_cream():
? ? return "Strawberry ice cream"
@add_toppings
def mango_ice_cream():
? ? return "Mango ice cream"
# Calling the ice cream functions
result_basic = basic_ice_cream()
result_chocolate = chocolate_ice_cream()
result_strawberry = strawberry_ice_cream()
result_mango = mango_ice_cream()
# Printing the results
print(result_basic)
print(result_chocolate)
print(result_strawberry)
print(result_mango)
Let's break down how the code works in Python step by step:
1. First, we define the `basic_ice_cream` function, which represents the core ice cream recipe.
2. Next, we define the `add_topping` decorator function. This function takes another function (`ice_cream_function`) as an argument and returns the `wrapper` function.
3. Inside the `wrapper` function, we call the `ice_cream_function()` that was passed as an argument. This is where the basic ice cream recipe is invoked.
4. The `wrapper` function also includes additional functionality, such as adding a topping to the ice cream. In this case, the decorator adds the specified topping to the basic ice cream.
5. After defining the decorator, we create three new ice cream functions: `chocolate_ice_cream`, `strawberry_ice_cream`, and `mango_ice_cream`. Each of these functions is created by decorating the `basic_ice_cream` function using the `add_topping` decorator. This means that each type of ice cream includes the basic ice cream recipe and the specified topping.
6. Finally, when we call each of the ice cream functions (`result_chocolate`, `result_strawberry`, `result_mango`), the decorator adds the corresponding topping to the basic ice cream recipe.
In essence, the decorator wraps the basic ice cream recipe with additional functionality (topping) while keeping the core recipe unchanged. This approach allows us to create different variations of ice creams using a common base recipe.
Control Flow for Each Function Call:
1. When `result_basic` is called, the `basic_ice_cream` function is invoked directly. It returns the basic ice cream recipe without any toppings.
2. When `result_chocolate` is called, the `chocolate_ice_cream` function is invoked. The `add_topping` decorator adds the "chocolate" topping to the basic ice cream recipe, and the decorated ice cream is returned.
3. Similarly, when `result_strawberry` is called, the `strawberry_ice_cream` function is invoked. The decorator adds the "strawberry" topping to the basic ice cream recipe, and the decorated ice cream is returned.
4. When `result_mango` is called, the `mango_ice_cream` function is invoked. The decorator adds the "mango" topping to the basic ice cream recipe, and the decorated ice cream is returned.
By using decorators, we can add different toppings to the same basic ice cream recipe and create various ice cream flavors with ease.
The decorator helps separate the core functionality (basic ice cream) from the additional features (toppings) while allowing for flexibility and modularity in our code.
Now, let's switch from ice cream to the world of programming. Imagine you're building a web application that handles various user interactions. You've written functions to register users, process data, and render content. Everything works smoothly, until your manager drops a request: "We need to log every user interaction for analytics."
The Developer's Challenge
Logging every user interaction is essential, but you don't want to clutter your functions with logging code. Enter decorators, the programming equivalent of adding decorations to your ice cream.
In our web application scenario, functions act as the main ingredients, just like the toppings on basic ice cream. These functions process requests, perform calculations, and provide responses. Just like your basic ice creams' core recipes, you want to keep these functions clean and focused on their tasks.
Closing Remarks
The decorator acts as a wrapper around the original function, allowing additional functionality to be added seamlessly. I hope you enjoyed reading the article.
Stay tuned for more Python fun in the next edition!
Happy Coding!