## Function Chaining in Python

Let me start with a little example. If you have a bunch of operations to perform on an input that you want to chain together (i.e. output of operation 1 into input of operation 2, ...), it is fairly easy to write a bunch of functions and then call them in order (perhaps even to write another function to call all of these functions in order). But, what if you want to make a bunch of different variations to this chain such as the order of the operations (functions which are not commutative; a - > b != b -> a), add new functions to the chain, or, for testing, create a bunch of chains with a variety of different input parameters?

Fortunately, Python makes this easy (thanks Dict()).

Let's see some code:

First, we'll make a couple different functions:

```
def multiply(input_, **kwargs):
return input_ * kwargs.get('value', 1)
```

```
def power(input_, **kwargs):
return input_ ** kwargs('pow', 2)
```

The above functions have the same interface: `input_`

which in our case will be the input signal and `**kwargs`

which is a fancy way of sending an arbitrary amount of other arguments (in the form of a dictionary; for example, you could call `multiply(input_, an_argument=10, whatever= 'yes!', any_other_argument = 2)`

).

Furthermore, you can see that each of these functions returns their result. This is important because we're going to pass the output of functions into other functions.

Next, we'll put the references to these functions into a list (with some arguments!). I'll call this composing a signal chain.

```
signal_chain = [
{'function': multiply, 'value': 2},
{'function': power, 'pow': 2} ]
```

You'll notice there are two dictionaries packed into a list. This allows us to iterate through the list and to handle each operation in sequence. The `'function'`

dictionary key has the function pointer. The second key in each dictionary acts as our input arguments for the functions that will be called.

Next, let's make a function to handle chaining these operations together.

```
def chain(input_, operations):
for operation in operations:
input_ = operation['function'](input_, **operation)
return input_
```

Hopefully this doesn't seem too weird.

The first statement (`for operation in operations:`

) takes each element in the list (in order) and assigns it to the variable `operation`

. This dictionary (because each element in our list is a dictionary) is then used in the next line.

Here's the tricky part, the `'function'`

key in the `operation`

dictionary returns a function, this is passed two arguments: `(input_, **operation)`

`input_`

is the value we're getting the function to manipulate and return.

`**operation`

is a funny thing: first, we're actually sending our temporary dictionary (`operation`

, the dictionary containing our function and parameters). We can send the whole dictionary without issue because the `**`

before the dictionary name makes the function's second argument properly parse the dictionary.
And so, because the second argument for all of our functions is `**kwargs`

, which allows an arbitrary number of input, we don't have to worry that the dictionary has extra information not used by the function.

To illustrate this, take another look at the `power`

function: because `kwargs`

is in fact the dictionary we put in, we can use any key we like contained. So, the `input_`

is taken to the power of the value contained at `kwargs['pow']`

. Since the other keys are not called in the function, the function does not care that `kwargs`

contains a reference to the function itself.

### In action:

```
signal_chain1 = [
{'function': multiply, 'value': 2},
{'function': power, 'pow': 2} ]
signal_chain2 = [
{'function': power, 'pow': 2},
{'function': multiply, 'value': 2}]
out1 = chain(3, signal_chain1)
out2 = chain(3, signal_chain2)
print 'out1', out1
print 'out2', out2
out1 36
out2 18
```