Module (40%)
Section (31%)

Decorators should be universal

Consider a function that accepts arguments and should also be decorated. Decorators, which should be universal, must support any function, regardless of the number and type of arguments passed. In such a situation, we can use the *args and **kwargs concepts. We can also employ a closure technique to persist arguments.

The code presented in the right pane shows how the decorator can handle the arguments of the function being decorated.

The output is:

"combiner" was called with the following arguments ('a', 'b') {'exec': 'yes'} Hello from the decorated function; received arguments: ('a', 'b') {'exec': 'yes'} Decorator is still operating

output

Arguments passed to the decorated function are available to the decorator, so the decorator can print them. This is a simple example, as the arguments were just printed, but not processed further.

A nested function (internal_wrapper) could reference an object (own_function) in its enclosing scope thanks to the closure.


Code

def simple_decorator(own_function):

def internal_wrapper(*args, **kwargs):
print('"{}" was called with the following arguments'.format(own_function.__name__))
print('\t{}\n\t{}\n'.format(args, kwargs))
own_function(*args, **kwargs)
print('Decorator is still operating')

return internal_wrapper


@simple_decorator
def combiner(*args, **kwargs):
print("\tHello from the decorated function; received arguments:", args, kwargs)

combiner('a', 'b', exec='yes')
{{ dockerServerErrorMsg }} ×
{{ errorMsg }} ×
{{ successMsg }} ×