# Pieces of Py #2: Use a dictionary instead of multiple if-statements

Posted on Thu 01 August 2019 in Python • 4 min read

One thing I learned during my first #100DaysOfCode was to use a dict instead of numerous if-statements. In my opinion it can make the code much more readable among other things. Here I'll try to make an example where this concept could fit in.

In this example we create a very simple calculator, that takes three parameters. As you can see we are using standard if-statements here. It could have been if-elses, but I think that makes it even harder to read.

```
def calculate(operator: str, value1: int, value2: int):
"""
The calcluate function takes three arguments and returns the
result of the asked for calculation.
operator: a string that determines what kind of calculation to do.
value1: an integer of the first value to be calculated
value2: an integer of the second value to be calculated
"""
if operator == 'add':
return value1 + value2
if operator == 'sub':
return value1 - value2
if operator == 'mul':
return value1 * value2
if operator == 'div':
return value1 / value2
return None
```

Below you see the results of calling this function with it's different operators. I know, there is no error handling in this function whatsoever, but I try to keep it simple here and stay on topic.

```
calculate('add', 1, 2)
```

`3`

```
calculate('sub', 1, 2)
```

`-1`

```
calculate('mul', 1, 2)
```

`2`

```
calculate('div', 1, 2)
```

`0.5`

### Using a dict instead of if-statements

Let's rewrite the calculate function, get rid of the if-statements and create a dict with out operators as keys, and a function (lamda in this case) as the value. If there had been more complex fuctions, I could have lifted out those to its own functions, and just put the function names as values in the dict.

But in this case let's go with some lambdas.

```
def calculate(operator: str, value1: int, value2: int):
operate = {
'add': lambda x, y: x + y,
'sub': lambda x, y: x - y,
'mul': lambda x, y: x * y,
'div': lambda x, y: x / y,
}
# We use the get method on our operate dict to get the desired function.
# The my_operator variable becomes the function we want to use.
# If the operator string we get as input isn't found in the dict,
# the my_operator in this case gets 'None'
my_operator = operate.get(operator, None)
return my_operator(value1, value2)
```

Calling our new function below, returns the same results as before.

```
calculate('add', 1, 2)
```

`3`

```
calculate('sub', 1, 2)
```

`-1`

```
calculate('mul', 1, 2)
```

`2`

```
calculate('div', 1, 2)
```

`0.5`

Of course this is a very simple example. If we for example call the function with a operator that doesn't exist, we get an error.

```
calculate('muldiv', 1, 2)
```

```
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-45-aad5c90e123c> in <module>
----> 1 calculate('muldiv', 1, 2)
<ipython-input-40-e74565bc1ae5> in calculate(operator, value1, value2)
15 my_operator = operate.get(operator, None)
16
---> 17 return my_operator(value1, value2)
TypeError: 'NoneType' object is not callable
```

This was a simple example to replace muliple if-statements with a dict, with keys and functions as values.

## Using a list of numbers as input

One thing that hit me when I did this in an exercise, was that the calculate function I did was very limiting. It could only calculate two values. I needed the input to be a list of numbers. How would I accomplish that and still use lambdas? (Of course I could've easily, broken out each lambda to it's own separate function)

It turns out there was something in the functools library that I could use in this case - functools.reduce.

A quote from the functools.reduce documentation:

Apply function of two arguments cumulatively to the items of sequence, from left to right, so as to reduce the sequence to a single value. For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates ((((1+2)+3)+4)+5)

With functools.reduce I could use the lambda function as the first parameter, and send in a list of number as the second parameter.

```
import functools
def calculator(operation: str, numbers: list):
operations = {
'add': functools.reduce(lambda x, y: x + y, numbers),
'sub': functools.reduce(lambda x, y: x - y, numbers),
'mul': functools.reduce(lambda x, y: x * y, numbers),
'div': functools.reduce(lambda x, y: x / y, numbers),
}
return operations.get(operation)
```

```
calculator('add', [1, 2, 3, 4])
```

`10`

```
calculator('sub', [1, 2, 3, 4])
```

`-8`

```
calculator('mul', [1, 2, 3, 4])
```

`24`

```
calculator('div', [1, 2, 3, 4])
```

`0.041666666666666664`

### Conclusion

In this article I've given an easy example on how to use a dictionary instead of multiple if-statements to sort of emulate a switch/case statement. Since Python dictionaries can take almost anything as values for different keys, we used a function as the value which we then used to calculate numbers.

### Resources

- Emulating switch/case Statements in Python (Real Python)
- Functools -- Higher-order functions and operations on callable objects (Python Documentation)

Let me know on Twitter if I can improve this article, or if you have other resources to help out with understanding this topic.