Advanced Topics in Python: Decorators and Context Managers

Akshobya KLAkshobya KL
3 min read

Now that we have covered modules and how to better structure our Python code, let’s dive into some more advanced topics decorators and context managers. These are two powerful features that can significantly improve the way we write and manage code.

How Do Decorators Work?

Understanding Python Decorator: Concepts, Functions, & More

In Python, functions are first class citizens, meaning they can be passed around and used as arguments. A decorator is essentially a function that takes another function and extends its behavior.

Example:

def decorator_function(original_function):
    def wrapper_function():
        print("This runs before the original function.")
        original_function()
        print("This runs after the original function.")
    return wrapper_function

@decorator_function
def say_hello():
    print("Hello!")

say_hello()

output will be,
This runs before the original function.

Hello!

This runs after the original function.

By using the @decorator_function syntax, we’ve wrapped say_hello() with additional behavior, without modifying the function itself.

When Should We Use Decorators?

  • Logging: Automatically log the execution of certain functions without manually adding print statements.

  • Authorization: Check permissions or access control before executing certain functions.

  • Timing: Measure how long a function takes to run.

Context Managers: Simplifying Resource Management

Context Manager in Python

Another advanced Python feature we can utilize is the context manager. Context managers allow us to properly manage resources such as file handling, database connections, or network sockets. They ensure that resources are automatically cleaned up after use, even if an error occurs, making our code more robust.

How Do Context Managers Work?

The most common example of a context manager is the with statement used for file handling.

Example:

with open('example.txt', 'r') as file:
    content = file.read()
    print(content)

In this example, the with statement automatically closes the file after the block of code is executed, even if an error occurs within the block. This eliminates the need for manual close() calls and reduces the chances of forgetting to release resources.

Creating a Custom Context Manager

We can also create our own context managers using the contextlib module

Here’s how to create a simple custom context manager using the contextlib module:

from contextlib import contextmanager

@contextmanager
def my_context():
    print("Before")
    yield
    print("After")

with my_context():
    print("Inside the context")

Before

Inside the context

After

The yield statement is where the block of code within the with statement will run. Before and after that block, the additional behavior we defined in the context manager is executed.

When Should We Use Context Managers?

  • File or database connections: Automatically manage open and close operations.

  • Locking mechanisms: Ensure that locks are properly acquired and released.

  • Resource allocation: Handle the setup and teardown of any resources that need to be managed.

Conclusion

Decorators and context managers are two advanced Python features that bring a lot of power and flexibility to our code. Decorators allow us to enhance functions dynamically, making our code more modular and reusable, while context managers help us manage resources efficiently and safely. By mastering these tools, we can write cleaner, more reliable Python code that handles complex tasks with ease.

0
Subscribe to my newsletter

Read articles from Akshobya KL directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Akshobya KL
Akshobya KL

Full stack developer dedicated to crafting seamless user experiences. I thrive on transforming complex problems into elegant solutions!