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
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
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))
There you go. Quick, visual, easy. Hope this helps someone ...!
Top comments (0)