Wednesday, October 7, 2015

Python Decorators Examples

I often go long stretches between times when I aggressively use python at clients.  As a result, I get rusty on what I could consider somewhat advanced topics and have to spend time googling around to jog my memory.  Reading my own code usually gets me back up and running quicker than reading others' code.  Leaving this here as a breadcrumb to help me remember how to use python decorators.

If you find this helpful, awesome!

#!/usr/bin/env python
"""Decorator examples"""

def decorator_without_arguments(func):
    def wrapped_function(*args, **kwargs):
        """Reverses the arguments before calling"""
        new_args = reversed(args)
        return func(*new_args, **kwargs)
    wrapped_function.__name__ = "(%s -> %s)" % \
        (decorator_without_arguments.__name__, func.__name__)
    return wrapped_function

def decorator_with_arguments(arg1, arg2=None):
    def actual_decorator(func):
        def wrapped_function(*args, **kwargs):
            """Wraps results in explanation string"""
            result = "(%s: %s) " % (arg1, ', '.join([str(x) for x in args]))
            result += str(func(*args, **kwargs))
            if arg2 is not None:
                result += arg2
            return result
        wrapped_function.__name__ = func.__name__
        return wrapped_function
    return actual_decorator


def undecorated_subtract(number_1, number_2):
    return number_1 - number_2

@decorator_without_arguments
def decorated_subtract(number_1, number_2):
    return number_1 - number_2

def undecorated_add(number_1, number_2):
    return number_1 + number_2

@decorator_with_arguments('ADD')
def decorated_add(number_1, number_2):
    return number_1 + number_2


if __name__ == '__main__':
    print undecorated_subtract(7, 3)
    print decorated_subtract(7, 3)
    print decorated_subtract
    print undecorated_add(3, 7)
    print decorated_add(3, 7)
    print decorated_add