Fundamentals 9 min read

Understanding Python Decorators: From Simple Functions to Advanced Usage

This article explains how Python decorators work by showing how to wrap functions for timing, handle arbitrary arguments, and create higher‑order decorators that can repeat calls, illustrating the power and flexibility of function wrapping in Python.

Python Programming Learning Circle
Python Programming Learning Circle
Python Programming Learning Circle
Understanding Python Decorators: From Simple Functions to Advanced Usage

Python treats functions as first‑class objects, allowing them to be assigned to variables, passed as arguments, and returned from other functions. Decorators are essentially functions that wrap other functions to add new behavior without modifying the original function's code.

We begin with a simple add function that adds two numbers and demonstrate manual timing by inserting code before and after the call, which quickly becomes repetitive when many functions need the same behavior.

To avoid duplication, a higher‑order function timer(func) is introduced. It returns a new function f(x, y=10) that records the start time, calls the original function, records the end time, prints the elapsed time, and returns the result. By assigning add = timer(add) we achieve the same effect as a decorator.

The decorator syntax @timer is then shown, which is syntactic sugar for the assignment add = timer(add) . This makes the code clearer and more concise.

To make the decorator applicable to any function, the implementation is updated to accept arbitrary positional and keyword arguments using *args and **kwargs . This version of timer can wrap functions with any signature while preserving default values.

Finally, the concept of higher‑order decorators is demonstrated with a decorator factory ntimes(n) . It returns a decorator that repeats the wrapped function n times. An example shows @ntimes(3) applied to add , causing the function body to execute three times, and the combined use of @timer and @ntimes illustrates composability.

Key code examples:

# dec.py

def add(x, y=10):
    return x + y

# Simple timer decorator
from time import time

def timer(func):
    def f(*args, **kwargs):
        before = time()
        rv = func(*args, **kwargs)
        after = time()
        print('time taken:', after - before)
        return rv
    return f

@timer
def add(x, y=10):
    return x + y

# Higher‑order decorator to repeat calls

def ntimes(n):
    def inner(f):
        def wrapper(*args, **kwargs):
            for _ in range(n):
                rv = f(*args, **kwargs)
            return rv
        return wrapper
    return inner

@ntimes(3)
@timer
def add(x, y):
    print(x + y)
    return x + y
PythonCode ExampledecoratorfunctionTiminghigher-order
Python Programming Learning Circle
Written by

Python Programming Learning Circle

A global community of Chinese Python developers offering technical articles, columns, original video tutorials, and problem sets. Topics include web full‑stack development, web scraping, data analysis, natural language processing, image processing, machine learning, automated testing, DevOps automation, and big data.

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.