Skip to content

Latest commit

 

History

History
94 lines (74 loc) · 2.05 KB

45_functools_wrap.md

File metadata and controls

94 lines (74 loc) · 2.05 KB

The built-in library functools contains several utility functions for working with functions. See https://docs.python.org/2/library/functools.html One of the most important is partial, which we will see later.

Here we look at wraps, which makes decorators work in a slightly more convenient way. First let's try and create a decorator which might be useful. This one takes a function and turns it into a function which can deal with None being passed in.

>>> def protect_from_none(f):
...     def temp(x):
...         if x is None:
...             return None
...         return f(x)
...     return temp

We take a function which we could apply it to:

>>> def add_five(n):
...     """ Adds five to things. """
...     return n + 5
...
>>> add_five(10)
15
>>> add_five(None)
Traceback (most recent call last):
...
TypeError: unsupported operand type(s) for +: 'NoneType' and 'int'

Let's check some of the details of how this function is represented:

>>> add_five  # doctest: +ELLIPSIS
<function add_five at 0x...>
>>> add_five.__doc__
' Adds five to things. '

Now let's define the function again, this time using the decorator.

>>> @protect_from_none
... def add_five(n):
...     """ Adds five to things. """
...     return n + 5
...
>>> add_five(2)
7
>>> add_five(None)

It works, but we have messed up some of the metadata of the function a bit.

>>> add_five  # doctest: +ELLIPSIS
<function temp at 0x...>
>>> add_five.__doc__

To keep this metadata in the decorated function, we use wraps in the decorator.

>>> from functools import wraps
>>> def protect_from_none(f):
...     @wraps(f)
...     def temp(x):
...         if x is None:
...             return None
...         return f(x)
...     return temp

When we defined the function temp, we specified that it was supposed to be a replacement for f.

>>> @protect_from_none
... def add_five(n):
...     """ Adds five to things. """
...     return n + 5
...
>>> add_five  # doctest: +ELLIPSIS
<function add_five at 0x...>
>>> add_five.__doc__
' Adds five to things. '