In [2]:
from functools import wraps
def my_name(his_name="Bob"):
"""
In order to pass arguments to a function decorator, you need an outer layer that
accepts the arguments and returns the function decorator function.
"""
def my_name_decorator(function):
"""
The function decorator function accepts the decorated function as an argument
and contains a wrapper function that it must return.
"""
"""
The @wraps decorator is a helper decorator. See
https://docs.python.org/3.4/library/functools.html#functools.wraps for more
information.
"""
@wraps(function)
def my_name_wrapper(name):
"""
The wrapper function checks state and makes whatever modifications are
required. It should return whatever is expected from the decorated
function and it may even call the original function.
"""
print("My name is Chris, his name is {}".format(his_name))
return function(name)
return my_name_wrapper
return my_name_decorator
# Calling the function decorator with an argument uses the outer function to get
# the arguments into the scope of the decorator function.
@my_name(his_name="George")
def print_name_with_arg(name):
print("Your name is {}".format(name))
# when we don't have an argument, we still need the () so that the outer function
# will return the decorator function
@my_name()
def print_name_without_arg(name):
print("Your name is {}".format(name))
In [5]:
print_name_with_arg("Chris")
In [6]:
print_name_without_arg("Chris")