I have numerous reusable functions, all with the same signature (they take a record and return a float). I often need to combine functions into a new function.
Let's say I want to create  a function that takes a record, applies f to it, and if the result is negative converts it to zero. I have two ways of doing that: composition and function modification. What are the pros and cons of each approach?
Composition:
def non_negative(value):
    return max(0, value)
g = compose(non_negative, f)
# from functional module by Collin Winter
def compose(func_1, func_2, unpack=False):
    """
    compose(func_1, func_2, unpack=False) -> function
    The function returned by compose is a composition of func_1 and func_2.
    That is, compose(func_1, func_2)(5) == func_1(func_2(5))
    """
    if not callable(func_1):
        raise TypeError("First argument to compose must be callable")
    if not callable(func_2):
        raise TypeError("Second argument to compose must be callable")
    if unpack:
        def composition(*args, **kwargs):
            return func_1(*func_2(*args, **kwargs))
    else:
        def composition(*args, **kwargs):
            return func_1(func_2(*args, **kwargs))
    return composition
Modification:
def non_negative(func):
    def new_func(record):
        return max(0, func(record))
    return new_func
g = non_negative(f)    
 
     
    