Python function that takes two functions and returns the concatenated function?

Viewed 334

I need to write a python function called 'concat' that takes any two functions as input, and returns a function, which is the concatenated function of the two input functions (i.e. it takes f1 and f2, and returns f1◦f2).

I tried this:

def concat(f1,f2):
    return f1(f2)

So for example, if f1 and f2 are:

def f1(x):
    return x+2
def f2(x):
    return x*2

then, concat(f1,f2) should return: (x*2)+2

I want to be able to use it like this:

a = concat(f1,f2)
a(5)

But I get an error:

TypeError: unsupported operand type(s) for +: 'function' and 'int'

I know I can define the function like this:

def concat(f1,f2,x): 
    return f1(f2(x))

But that is not what I want; I want to be able to create instances of the concat function, which then can be called with any x.

3 Answers

I think what you want is a closure.

def concat(f1, f2):
  def f3(x):
    return f1(f2(x))
  return f3

Functions in Python are considered first class objects. This allows them to be created and manipulated like normal variables. In this case concat is constructing a new function that composes two functions.

The second property being used here is lexical scoping. The new function retains access to the local variables where it was defined not where it is executed. This allows the returned function to be run anywhere without losing access to the composite functions.

Here's a possible solution to compose more than two functions. Using a closure to loop through the functions and use the previous function's result as argument for the next one:

def compose(*fns):
    def F(x):
        for fn in fns[::-1]:
            x = fn(x)
        return x
    return F

Then define your composition and call:

>>> F = compose(f1, f2, lambda x: x+1)
>>> F(4)
12 # f1(f2(f3(x)))
Related