Function decorators in python
This is nice python syntax sugar that may look like magic but really isn't. It can be used for quick and easy AOP, registering functions with objects... you name it.
Python decorators are objects that are called, returning a function that wraps the function they decorate, taking the wrapped function object as an argument and replacing it with the wrapper function.
A simple decorating function can look like this:
def decorator(func): def wrapper(*args): return 'x' + func(*args) + 'x' return wrapper
and is used to decorate another function like this:
@decorator def test(): return "hello"
test will now return the string "xhellox".
* prefixed arguments
will accept an arbitrary number of arguments, putting them into a tuple, and
can be dereferenced into arguments again with
* in a function call. We use
this to pass all the non-keyword arguments in the wrapping function to the
wrapped function. Keyword arguments can similarly be extracted from
** and turned back into arguments in a function call with
This is good to know if you just want a "pass-through" decorator (maybe some sort of "logging" aspect) that works for any function or method.
Dynamically creating decorators
The simple example above can be extended to support different appending different characters, but the object following the "@" in the decorator still needs to resolve to a function. What if we could decorate as such:
@decorator('$') def test(): return "hello" >>> test() '$hello$'
The decorating function can now no longer be the function you use to generate
it, but the function it returns. The
decorator in the example above would be
def decorator_factory(prefix) def dec(func): # the actual decorator def wrapper(*args): return prefix + func(*args) + prefix return wrapper return dec @decorator_factory('$') def test(): return "hello" >>> test() '$hello$'
Decorators as classes or class members
A decorator can be any callable object. This includes classes and any object