Function Decorator Basics

Function decorators are used in many python packages and libraries. Often, you see the @ sign in code before you learn what it is, so you get back to read about decorators.
We'll use a simple example to demonstrate the use of decorators.

What do we try to achieve

  • Suppose you have a simple, 2 params function like the following:
1def add_nums(a,b):
2    return a+b
  • This is a simple one, but it has no defaults, so if you try to call it, say, with just one parameter, it would fail:
1>>> def add_nums(a,b):
2...     return a+b
3... 
4>>> 
5>>> add_nums(5)
6Traceback (most recent call last):
7  File "<stdin>", line 1, in <module>
8TypeError: add_nums() missing 1 required positional argument: 'b'
9>>> 
  • The "magic" we want to achieve, is that we "decorate" this function, so that it'll "change" the function so it gets defaults for its parameters:
 1>>> from add_defaults_decorator import add_defaults
 2>>> 
 3>>> @add_defaults
 4... def add_nums(a, b):
 5...   return a+b
 6... 
 7>>> 
 8>>> add_nums(3, 4)
 97
10>>> add_nums(4)
114
12>>> add_nums()
130
14>>> 

Decorator magic WITHOUT the decorator sign

This is what we'd do to create our function decorator:

  • We write the decorator function (add_defaults in our case)
  • This function accepts a two_params_func as a parameter, and returns ANOTHER function, one that:
    • has default values
    • calling the original 2 params function
1def add_defaults(two_params_func):
2    def two_params_with_defaults_func(a=0, b=0):
3        return two_params_func(a,b)
4    return two_params_with_defaults_func
  • ..so now, we can create our 2 params (default-less) function, then use add_defaults to replace it with a better version:
1def add_nums(a,b):
2    return a+b
3
4add_nums = add_defaults(add_nums)
  • Now, the name add_nums stays, but this is another function altogether.

Now, with the @ sign

  • Same thing:
 1def add_defaults(two_params_func):
 2    def two_params_with_defaults_func(a=0, b=0):
 3        return two_params_func(a,b)
 4    return two_params_with_defaults_func
 5
 6# The following decorator actually calls add_defaults, just the same:
 7
 8@add_defaults
 9def add_nums(a,b):
10    return a+b
  • Not that we do not call the decorator function itslef. We write a reference to it next to the @ sign, and let python call it.