Fundamentals 8 min read

Advanced Python Programming: Mastering Decorators for Cleaner, More Maintainable Code

This article introduces Python decorators, explains their underlying principles, demonstrates practical examples such as logging and retry mechanisms, and shows how to combine multiple decorators and class‑based decorators to create reusable, non‑intrusive enhancements for functions and methods.

Ctrip Technology
Ctrip Technology
Ctrip Technology
Advanced Python Programming: Mastering Decorators for Cleaner, More Maintainable Code

Python is praised for its elegance and ease of use, and decorators are a powerful feature that enable developers to add reusable functionality to functions or classes without modifying their core logic.

Part 1 – Getting Started : A simple log decorator is defined to print messages before and after a function call. The example shows how applying @log to a greeting function produces the output before , Hello, World! , after .

def log(f):
    def wrapper():
        print("before")
        f()
        print("after")
    return wrapper

@log
def greeting():
    print("Hello, World!")

greeting()

Part 2 – Under the Hood : Decorators work because functions are first‑class objects in Python; a decorator receives a function as an argument, returns a new function, and the original name is rebound to this new wrapper. The same effect can be achieved without the @ syntax by manually assigning greeting = log(greeting) .

def greeting():
    print("Hello, World!")

greeting = log(greeting)

Part 3 – Practical Use: Retry Logic : A retry decorator is introduced to automatically retry a flaky function (e.g., non_steady ) up to a configurable number of times, dramatically increasing success probability without changing call sites.

def retry(times=10):
    def outer(f):
        def inner(*args, **kwargs):
            for i in range(times):
                try:
                    return f(*args, **kwargs)
                except Exception as e:
                    if i + 1 >= times:
                        raise e
        return inner
    return outer

@retry(10)
def non_steady():
    if random.random() <= 0.5:
        raise Exception("died")
    return "survived"

This approach avoids code duplication and centralizes the retry policy.

Part 4 – Advanced Composition : Multiple decorators can be stacked, with the innermost applied first. An example combines @log and @retry(10) on the same function, illustrating the order of execution.

@log
@retry(10)
def greeting():
    print("Hello, World!")

Class‑Based Decorators : A class Log implements __call__ to act as a decorator, offering object‑oriented benefits such as encapsulation. Using @Log yields the same behavior as the function‑based log decorator.

class Log(object):
    def __init__(self, f):
        self.f = f
    def __call__(self, *args, **kwargs):
        print("before")
        self.f()
        print("after")

@Log
def greeting():
    print("Hello, World!")

greeting()

In conclusion, decorators provide a clean, maintainable way to extend functionality, improve readability, and promote code reuse in everyday Python development.

pythonProgrammingretrycode reusedecoratorAdvanced
Ctrip Technology
Written by

Ctrip Technology

Official Ctrip Technology account, sharing and discussing growth.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.