A decorator that uses the function it decorates to extend the function
provided as a parameter.
This is best illustrated with an example:
::
def x(a0, a1, a2):
rv0 = [a0, a1, a2]
rv1 = None
return rv0, rv1
@extend(x)
def y(rv0, rv1):
rv0.append(-1)
# We can now call `y` as if it were `x`, and we will receive
# the return values from `x` after any modifications by `y`
rv0, rv1 = y(1, 2, 3)
assert rv0 == [1, 2, 3, -1]
assert rv1 is None
In this case, ``extend`` is essentially syntactic sugar for:
::
def y(a0, a1, a2):
rv0, rv1 = x(a0, a1, a2)
# Body of `y` from previous section
rv0.append(-1)
return rv0, rv1
If ``y`` does not return anything, or returns ``None``, then ``extend`` will
ensure that the return value of ``x`` is forwarded to the caller.
This means that ``y`` will provide exactly the same interface as ``x``.
If `y` returns something other than ``None``, then its return value will be
provided to the caller, and the return value of ``x`` will be discarded.
NOTE: This function will automatically unpack tuples returned by the function
being extended. Thus, the following implementation of ``x`` would behave just like
the one mentioned above:
::
def x(a0, a1, a2):
ret = (rv0, rv1)
return ret # Tuple will be unpacked, and `y` still sees 2 parameters
Args:
extend_func (Callable): A callable to extend.