Functions as values¶

In the introduction to functions, we introduced the metaphor of a function being a recipe. It is a procedure, that accepts inputs, (the ingredients of the recipe), and returns an output (the meal from the recipe). A function, like a recipe, usually has a name.

```def add(a, b):
return a + b
```

As we saw before, this function gets its name from the first line. The name is `add`. The name `add` refers to the internal representation (IR) of the procedure of adding two numbers. In the same way “Double egg cheese omelette recipe” refers to the procedure of making a double egg cheese omelette. The recipe is a procedure that can be applied to two eggs and some cheese, as `add` is a procedure that can be applied to two numbers.

You have already seen Python giving names to things. Here is an assignment statement:

```x = 1
```

The statement gives the name `x` to the value 1.

In fact, the function definition above is doing something similar. It gives the name `add` to the procedure `a + b`.

`x` is a variable name, and so is `add`. Function names are just variables. As `x` refers to the number 1, `add` refers to the procedure defined in the function body.

With the variable `x`, I can display its value in the notebook like this:

```x
```
```1
```

In the same way, I can display the value of the variable `add`

```add
```
```<function __main__.add(a, b)>
```

`add` refers to the internal representation (IR) of the procedure. In order to apply the procedure to particular arguments, I have to call it. I do this by adding parentheses, with arguments inside:

```add(2, 3)
```
```5
```

Now you know that `add` is a variable referring to a procedure, what do you think you would get from the following?

```add * 2
```
```---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-6-f413df800d6c> in <module>

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

Why is this? Python evaluates the first expression `add`; it is a variable pointing to a internal representation of a function, so the first value is a function. The second value is IR of int 2. It tries to multiply the IR of a function by the IR of an int, and fails.

We can’t multiply `add` by a number, but we can multiply the result of calling `add`, because this evaluates to a number:

```add(2, 3) * 2
```
```10
```

A variable can point to a function¶

This will take a little getting used to.

Remember, an assignment statement gives a value (from the right-hand side) to the variable on the left-hand side.

```x = 1
```

As we know, we can read this as “The variable ‘x’ gets the value IR of 1”.

We also know from the section above, that the function is a value.

Can we set a variable to get a function as a value? Yes. Look at this:

```my_function = add
```

Read this in the normal way: “The variable ‘my_function’ gets the value …”. What is the value? The value is the result of evaluating `add`, and you now know that this is the internal representation (IR) of the function.

So we read the statement as “The variable ‘my_function’ gets the value IR of the function originally called ‘add’”.

What do you think we would see if we evaluate this expression: `my_function(2, 3)`?

What will Python do? It first evaluates `my_function`, and gets the value, which is the IR of the function. Then it sees the parentheses following, so it evaluates the arguments inside the brackets, and calls the function. What function? The function originally called “add”.

```my_function(2, 3)
```
```5
```

Remember that the expression `my_function` is not the same as the expression `my_function(2, 3)`. `my_function` evaluates to the IR of the function. `my_function(2, 3)` evaluates to result of calling the IR of the function, with the arguments 2 and 3.

Now try the functions as values exercises.