Industrial manufacturing
Industrial Internet of Things | Industrial materials | Equipment Maintenance and Repair | Industrial programming |
home  MfgRobots >> Industrial manufacturing >  >> Industrial programming >> Python

Mastering Python Decorators: Enhance Functions with Expert Techniques

Python Decorators

Decorators let you wrap functions with reusable logic, making your code more modular, readable, and maintainable. In this guide we build, explain, and apply decorators in real‑world scenarios.

Video: @Decorators in Python

Decorators in Python

Python’s decorators are a powerful metaprogramming tool that allows you to add behavior to functions or classes at definition time. Because everything in Python is an object—including functions and classes—decorators operate by taking one callable, wrapping it in another, and returning the new callable.


Prerequisites for Learning Decorators

Before diving in, you should be comfortable with the fact that in Python, functions are first‑class objects. Names are simply references bound to objects; the same function can be referenced by multiple names.

def first(msg):
    print(msg)

first("Hello")

second = first
second("Hello")

Output

Hello
Hello

Functions can be passed as arguments, returned from other functions, and even nested within other functions. These concepts—higher‑order functions, nested functions, and closures—are the building blocks of decorators.

def inc(x):
    return x + 1

def dec(x):
    return x - 1

def operate(func, x):
    result = func(x)
    return result

Usage:

>>>>> operate(inc,3)
4
>>> operate(dec,3)
2
def is_called():
    def is_returned():
        print("Hello")
    return is_returned

new = is_called()
new()

Output

Hello

Understanding closures is key: the nested function retains access to the enclosing scope, which is precisely what decorators exploit to store metadata or modify behavior.


Getting Back to Decorators

In Python, a decorator is simply a callable that accepts a function (or another callable) and returns a new callable. This returned function typically wraps the original, adding or altering functionality before or after the call.

def make_pretty(func):
    def inner():
        print("I got decorated")
        func()
    return inner

def ordinary():
    print("I am ordinary")

Example usage:

>>>>> ordinary()
I am ordinary
>>> pretty = make_pretty(ordinary)
>>> pretty()
I got decorated
I am ordinary

The decorator pattern keeps the original function’s semantics intact while augmenting it. To avoid manual reassignment, Python provides syntactic sugar with the @ symbol:

@make_pretty
def ordinary():
    print("I am ordinary")

This is equivalent to:

def ordinary():
    print("I am ordinary")
ordinary = make_pretty(ordinary)

Decorating Functions with Parameters

Many decorators must handle arbitrary arguments. The *args and **kwargs syntax lets you capture any positional or keyword arguments and forward them unchanged.

def works_for_all(func):
    def inner(*args, **kwargs):
        print("I can decorate any function")
        return func(*args, **kwargs)
    return inner

Handling edge cases is another common decorator use‑case. For instance, guarding against division by zero:

def smart_divide(func):
    def inner(a, b):
        print("I am going to divide", a, "and", b)
        if b == 0:
            print("Whoops! cannot divide")
            return
        return func(a, b)
    return inner

@smart_divide
def divide(a, b):
    print(a/b)

Usage:

>>>>> divide(2,5)
I am going to divide 2 and 5
0.4
>>> divide(2,0)
I am going to divide 2 and 0
Whoops! cannot divide

Chaining Decorators in Python

Decorators can be stacked. The order of application matters, as each decorator receives the function returned by the one below it.

def star(func):
    def inner(*args, **kwargs):
        print("*" * 30)
        func(*args, **kwargs)
        print("*" * 30)
    return inner

def percent(func):
    def inner(*args, **kwargs):
        print("%" * 30)
        func(*args, **kwargs)
        print("%" * 30)
    return inner

@star
@percent
def printer(msg):
    print(msg)

Result:

******************************
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Hello
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
******************************

Reversing the order swaps the surrounding patterns, demonstrating how decorator stacking influences behavior.

Python

  1. Master Python Functions: Syntax, Types, and Practical Examples
  2. Mastering Python Function Arguments: Positional, Keyword, and Default Parameters
  3. Mastering Python Recursion: How Functions Call Themselves
  4. Python Lambda Functions: A Practical Guide to Anonymous Functions
  5. Python Generators: Efficient Iteration and Advanced Use Cases
  6. Python Closures Explained: How Nested Functions Capture Variables
  7. Mastering Python’s strip() Method: Comprehensive Guide & Practical Examples
  8. Python round() Function Explained with Practical Examples
  9. Mastering Python's map() Function: Syntax, Examples, and Best Practices
  10. Python Functions Explained: Building Reusable Code Modules