Fundamentals 16 min read

Master Python Decorators: From Basics to Advanced Techniques

This comprehensive guide explains Python decorators, covering basic concepts, practical examples, common pitfalls, and advanced patterns such as parameterized, class-based, and built‑in decorators, while showing how to avoid signature issues and improve readability with tools like functools.wraps, decorator, and wrapt.

MaGe Linux Operations
MaGe Linux Operations
MaGe Linux Operations
Master Python Decorators: From Basics to Advanced Techniques

Decorators are a crucial Python concept that often serve as a gate‑keeper for advanced programming. This article provides a thorough introduction, practical code examples, and best‑practice recommendations.

Why Use Decorators?

Suppose you have two functions say_hello() and say_goodbye(). You want to log entry time and name for each call without modifying the functions themselves.

def say_hello():
    print("hello!")

def say_goodbye():
    print("goodbye!")

if __name__ == '__main__':
    say_hello()
    say_goodbye()

Adding logging manually leads to repetitive code. Decorators let you inject such behavior transparently.

How to Write a Simple Decorator

Before Python 2.4, you would manually wrap a function:

def debug(func):
    def wrapper():
        print("[DEBUG]: enter {}()".format(func.__name__))
        return func()
    return wrapper

def say_hello():
    print("hello!")

say_hello = debug(say_hello)  # add logging without changing the original function

Using the @ syntax makes this cleaner:

def debug(func):
    def wrapper():
        print("[DEBUG]: enter {}()".format(func.__name__))
        return func()
    return wrapper

@debug
def say_hello():
    print("hello!")

Handling Arguments

If the wrapped function takes parameters, the wrapper must accept them as well. The most flexible approach uses *args and **kwargs:

def debug(func):
    def wrapper(*args, **kwargs):
        print("[DEBUG]: enter {}()".format(func.__name__))
        return func(*args, **kwargs)
    return wrapper

Parameterized Decorators

When the decorator itself needs configuration (e.g., a log level), you create a decorator factory:

def logging(level):
    def wrapper(func):
        def inner_wrapper(*args, **kwargs):
            print("[{}]: enter function {}()".format(level, func.__name__))
            return func(*args, **kwargs)
        return inner_wrapper
    return wrapper

@logging(level='INFO')
def say(message):
    print(message)

Class‑Based Decorators

A class can act as a decorator by implementing __call__:

class Logging(object):
    def __init__(self, func):
        self.func = func
    def __call__(self, *args, **kwargs):
        print("[DEBUG]: enter function {}()".format(self.func.__name__))
        return self.func(*args, **kwargs)

@Logging
def say(message):
    print(message)

Built‑in Decorators

Python provides several built‑in decorators such as @property, @staticmethod, and @classmethod. They work by returning descriptor objects rather than plain functions.

Common Pitfalls

Printing or executing code outside the wrapper can interfere with the decorator’s behavior.

Without functools.wraps, the wrapped function loses its original name, docstring, and metadata.

Inspecting the original signature or source may fail; third‑party libraries like wrapt preserve these details.

Decorating @staticmethod or @classmethod must be ordered correctly (decorator before the built‑in).

Improving Decorators

Libraries such as decorator and wrapt simplify implementation and retain function metadata. Example with wrapt:

import wrapt

@wrapt.decorator
def logging(wrapped, instance, args, kwargs):
    print("[DEBUG]: enter {}()".format(wrapped.__name__))
    return wrapped(*args, **kwargs)

@logging
def say(message):
    print(message)

These tools handle edge cases like preserving the original source, signature, and proper handling of class methods.

Conclusion

Python decorators differ from Java annotations or C# attributes; they wrap functions or objects to add behavior at call time. Understanding basic, parameterized, and class‑based decorators, as well as common pitfalls, enables clean, reusable code for logging, caching, authentication, and more.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

PythonprogrammingDecoratorcodeAdvanced
MaGe Linux Operations
Written by

MaGe Linux Operations

Founded in 2009, MaGe Education is a top Chinese high‑end IT training brand. Its graduates earn 12K+ RMB salaries, and the school has trained tens of thousands of students. It offers high‑pay courses in Linux cloud operations, Python full‑stack, automation, data analysis, AI, and Go high‑concurrency architecture. Thanks to quality courses and a solid reputation, it has talent partnerships with numerous internet firms.

0 followers
Reader feedback

How this landed with the community

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.