A 3-Min Primer on Python Decorators

Say, you are working for a large bank.

Your hacker colleague implemented a magic function that uses SSH to log into the bank’s core server (written in COBOL which you don’t know at all), analyzes the CPU usage over the last 24 hours, and returns the result as a cryptic string value.

Your boss asks you to modify the magic function so that it returns an integer value that is easier to process. In other words, your secondary bank application (written in Python) expects from now on that every call of the magic_function results in an integer value.

Of course, you could go into the code of the magic_function and rewrite it…

… But you wouldn’t risk breaking the application and losing millions of dollars, would you? Yet, you must touch it because existing functions outside of your control are already calling the magic_function!

The solution is simple: use a wrapper function and assign it to the name of the magic_function! Here’s how you’d accomplish this:

def integer_decorator(func):
    ''' Returns a function that converts the output of func to an integer. '''

    def wrapper():
        output = func()
        s = 0
        for x in output.split("+"):
            s += int(x)
        return s

    return wrapper


# This function is written by your hacker colleague.
# You don't want to touch it!
def magic_function():
    # ... complex stuff happening here ...
    return "89898292211+1123+13"

magic_function = integer_decorator(magic_function)

# ... somewhere in the code...
print(magic_function())
# 89898293347

As you see, you don’t touch the magic_function but its behavior still changed! To accomplish this, you first create a function integer_decorator that takes a function argument func and returns a wrapper function that converts the string output to an integer.

We then assign this wrapper function to the name magic_function and, thus, change the behavior of the magic_function when it is used in the code. This happens in the line magic_function = integer_decorator(magic_function).

A decorator simply returns a new function object that “decorates” (or modifies) an existing function that is passed as an argument. In our case, the integer_decorator returns a modified magic_function.

There’s some syntactical sugar of how you can accomplish the same thing a bit easier. The line magic_function = integer_decorator(magic_function) modifies the behavior of the magic_function. The same can be achieved when “decorating” the magic_function using the @ keyword:

@integer_decorator
def magic_function():
    # ... complex stuff happening here ...
    return "89898292211+1123+13"


# ... somewhere in the code...
print(magic_function())
# 89898293347

This way, you can easily enrich any function with additional functionality just by using the @ keyword.

Where to Go From Here?

Python experts today earn six-figure salaries or more. Becoming a Python coder is a profitable life choice with huge benefits for you and your family!

How do you become an expert? Simple: read more coding books than your colleagues! While your colleagues will read only one coding book per year (max), you can read one book per week to get a 52x advantage over most coders.

Buy the “Coffee Break Python” bundle now!

Leave a Comment