@Gary-Gordon
That is called a decorator function. This works by wrapping the existing function in another function, a decorating function, that allows for adding functionality to an existing function.
For example: Let's say that we have a function add
that just adds two numbers.
def add(x, y):
return x + y
However, the boss has come by an ask to add logging to that function so we know when it runs. How can we add this functionality for our application only without affecting the add
function in other places? Let's decorate!
def logit(func):
def wrapper(*args, **kwargs):
print("Calling function: {}".format(func.__name__))
results = func(*args, **kwargs) # down below this will be where **add** is called
print("Called function: {}".format(func.__name__))
print("Results: {}".format(results))
return results
return wrapper
add_with_logging = logit(add) # this is alternative to use the @ notation
results = add_with_logging(3, 2)
print("Results: (Expected -> 5) Actual -> {}".format(results))
Because we have writting this logit
function, we can now add logging to any functions that we write ourselves. Instead of add_with_logging = logit(add)
, we can use the shorthand:
@logit
def create_connection(address):
"""Makes a connection"""
...code here...
Which will add logging to the create_connection
function instead of us muddying up the internals of the function.
Decorators are convenient, but can take a bit to wrap your head around. Hope this helps.