DEV Community

Cover image for Python Decorator Quick-Reference
TaiKedz
TaiKedz

Posted on • Edited on

2 1

Python Decorator Quick-Reference

(Image (C) Tai Kedzierski)

There are plenty of lenghty tutorial posts out there about what Python decorators are, and the step by step incremental construction of one.

But sometimes all we need is a simple quick refresher. Here's mine (also on Gist).

Basic concepts

A Python decorator is a special function that can be added above a callable definition (function, class, anything that implements the __call__() method)

When a decorated function is called, it is in fact the decorator itself that is called, and the wrapped callable is then normally called by the implementing handler of the decorator.

A Python decorator is comprised of 3 parts:

  • name
  • wrapped function receiver
  • decorator implementation handler

A simple decorator

In a simple decorator, the name and the function receiver are one. It supplies a handling function, which should call the wrapped function, then return its result. The naming function must return the handler function.

def printres(func): # decorator name, wrapped function receiver

    def handler(*args, **kwargs): # decorator handling function
        res = func(*args, **kwargs)
        print("{}: {}".format("Result", res))
        return res
    return handler

Enter fullscreen mode Exit fullscreen mode

A decorator with parameters

In a parameterised decorator, the name and receiver are separated into two functions. The outermost function names the decorator and takes its parameters. The first inner function is a wrapper to receive the target function.

We need to import functools and use its 'wraps' decorator to munge the handler, since it is displaced by 1 level, and can cause oddities when stack traces are raised, making debugging difficult. The inner function returns the handler, and the outer function returns the inner function receiver.

import functools

def printmsg(message): # decorator name, decorator parameters

    def function_receiver(func): # wrapped function receiver
        @functools.wraps(func) # munge func so that stack traces and call sequences are retained

        def handler(*args, **kwargs): # decorator handling function
            res = func(*args, **kwargs)
            print("{}: {}".format(message, res))
            return res
        return handler
    return function_receiver
Enter fullscreen mode Exit fullscreen mode

Example usage

@printres
def plus(x, y):
    return x+y


@printmsg("minus")
def minus(x, y):
    return x-y


z1 = plus(2,3)
z2 = minus(3,6)

print("Final print: {} // {} ".format(z1,z2))
Enter fullscreen mode Exit fullscreen mode

There you go. Quick, visual, easy. Hope this helps someone ...!

Heroku

Simplify your DevOps and maximize your time.

Since 2007, Heroku has been the go-to platform for developers as it monitors uptime, performance, and infrastructure concerns, allowing you to focus on writing code.

Learn More

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay