Skip to content

Instantly share code, notes, and snippets.

@taikedz
Last active January 10, 2022 11:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save taikedz/47603180e2384a195e8740143a121eb3 to your computer and use it in GitHub Desktop.
Save taikedz/47603180e2384a195e8740143a121eb3 to your computer and use it in GitHub Desktop.
Python Decorator Example
"""
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
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.
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.
"""
# --------- Simple decorator
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
# --------- Decorator with its own parameters
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
# ----------- Usage demo
@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))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment