Skip to content

Python decorators usage and example

homepage-banner

Python decorators are a powerful feature that allows you to modify the behavior of functions, classes, and methods in Python. Decorators are functions that take another function as an argument, and then they add some functionality to the original function without modifying its source code. In this blog post, we will explore the usage of Python decorators and provide some examples.

Simple example

def hello(func):
    def inner():
        print("Hello ")
        func()
    return inner

def name():
    print("Alice")

obj = hello(name)
obj()

In the above example, hello() is a decorator. the function name() is decorated by the function hello(). It wraps the function in the other function.

Syntactic sugar

@hello
def name():
    print("Alice")

if __name__ == "__main__":
    name()

Decorated function with arguments

def pretty_sumab(func):
    def inner(a,b):
        print(str(a) + " + " + str(b) + " is ", end="")
        return func(a,b)

    return inner

@pretty_sumab
def sumab(a,b):
    summed = a + b
    print(summed)

if __name__ == "__main__":
    sumab(5,3)

More general case

def use_logging(level):
    def decorator(func):
        def wrapper(*args, **kwargs):
            if level == "warn":
                logging.warn("%s is running" % func.__name__)
            elif level == "info":
                logging.info("%s is running" % func.__name__)
            return func(*args)
        return wrapper

    return decorator

@use_logging(level="warn")
def foo(name='foo'):
    print("i am %s" % name)

if __name__ == "__main__":
    foo()

Decorator with arguments

def simple(type_):

    def wrapper(func):
        def decorate(test_, redis_):
            print("[Decorate %s] %s, %s" % (type_, test_, redis_))
            return func(test_, redis_)

        return decorate

    return wrapper


@simple("get")
def t_get(t, r):
    print("GET %s, %s" % (t, r))


@simple("set")
def t_set(t, r):
    print("SET %s, %s" % (t, r))


if __name__ == '__main__':
    t_get("aa", "bb")
    t_set("cc", "dd")

Class decorator

class Foo(object):
    def __init__(self, func):
        self._func = func

    def __call__(self):
        print ('class decorator runing')
        self._func()
        print ('class decorator ending')

@Foo
def bar():
    print ('bar')

if __name__ == "__main__":
    bar()

Decorator order

@a
@b
@c
def f ():
    pass

## euqals to 

f = a(b(c(f)))

Using wrapt

import wrapt

def with_arguments(myarg1, myarg2):
    @wrapt.decorator
    def wrapper(wrapped, instance, args, kwargs):
        return wrapped(*args, **kwargs)
    return wrapper

@with_arguments(1, 2)
def function():
    pass

if __name__ == "__main__":
    function()

Using decorator

#!/usr/bin/env python
from decorator import decorate
from datetime import datetime

def wrapper(func, *args, **kwargs):
    """print log before a function."""
    print("[DEBUG] {}: enter {}()".format(datetime.now(), func.__name__))
    return func(*args, **kwargs)

def logging(func):
    return decorate(func, wrapper)

@logging
def foo(name='foo'):
    print("i am %s" % name)

if __name__ == "__main__":
    foo()

Python decorators are a powerful feature that allows you to modify the behavior of functions, classes, and methods in Python. In this blog post, we explored some common use cases for Python decorators and provided examples. With decorators, you can add functionality to your code without modifying its source code, making your code more modular and easier to maintain.

Reference

  • https://pythonbasics.org/decorators
  • https://wrapt.readthedocs.io/en/latest/quick-start.html
  • https://foofish.net/python-decorator.html
  • The Python Book by Rob Mastrodomenico, 2022
Leave a message