A Switch Story

Python Switch Case

What is a switch?

The switch is a statement that evaluates the accuracy or similarity of the value of a certain input. But isn’t that the same thing that the if statement does? Let’s see this statement starting with bash scripting language.

case EXPRESSION in

  PATTERN_1)
    STATEMENTS
    ;;

  PATTERN_2)
    STATEMENTS
    ;;

  PATTERN_N)
    STATEMENTS
    ;;

  *)
    STATEMENTS
    ;;
esac

EXPRESSION is an expression (command) or a variable. PATTERN_N, is a value that is expected from EXPRESSION. * is default value.

So given an EXPRESSION, I evaluate the PATTERN cases and if they don’t fit into the latter, the default * comes into play. Simple. Let’s see her at work.

Switch, work!

Which fruit do you want?

echo -n "Enter the name of a fruit "
read FRUIT

echo -n "The $FRUIT is "

case $FRUIT in

  apple)
    echo -n "apple"
    ;;

  banana)
    echo -n "banana"
    ;;

  blueberries | raspberries | "blue currant" | currant)
    echo -n "berries"
    ;;

  *)
    echo -n "unknown"
    ;;
esac

In bash everything is very simple and clear. Let’s see what happens in other languages.

Switch in other languages

In other languages such as Java and .NET C#, the switch case is a bit more complicated. However, compared to the simplicity of the bash case, the purpose is clear. An example in Java.

public class FruitSelector  
{ 
    public static void main(String[] args) 
    { 
        String fruit = "banana";

        switch(fruit) 
        { 
            case "apple": 
                System.out.println("The fruit is apple"); 
                break; 
            case "banana": 
                System.out.println("The fruit is banana"); 
                break; 
            case "blueberries":
            case "raspberries":
            case "blue currant":
            case "currant":
                System.out.println("The fruit is berries"); 
                break; 
            default: 
                System.out.println("The fruit is unknown"); 
        } 
    } 
} 

And one in C#.

using System;

public class FruitSelector
{
   public static void Main()
   {
      string fruit = "banana";

      switch (caseSwitch)
      {
          case "apple":
              Console.WriteLine("The fruit is apple"); 
              break;
          case "banana": 
              Console.WriteLine("The fruit is banana"); 
              break;
          case "blueberries":
          case "raspberries":
          case "blue currant":
          case "currant":
              Console.WriteLine("The fruit is berries");
              break;
          default:
              Console.WriteLine("The fruit is unknown");
              break;
      }
   }
}

They are very similar. We built a fruit selector, like the one in bash.

But in python?

Python does not have any switch statements. A PEP 3103 has been evaluated and created, but the conclusion is:

In the mean time, Python is fine without a switch statement, and perhaps those who claim it would be a mistake to add one are right.

As I was reflecting above, the switch case is very similar to the if statement. An early form of switch in python could be given by if/elif/else statements.

fruit = "banana"
if fruit == "apple":
    print("The fruit is apple")
elif fruit == "banana":
    print("The fruit is banana")
elif fruit in ("blueberries", "raspberries", "blue currant", "currant"):
    print("The fruit is berries")
else:
    print("The fruit is unknown")

This is simple to both read and understand. But it’s still not a switch statement. The switch evaluates the accuracy but also the similarity of a word. There is an object in python which acts as a selector. Not for nothing have the two classes written in Java and C# above called “Selector”.

A selector evaluates an EXPRESSION, takes its value and checks the accuracy of the PATTERN, otherwise, it returns a default value (*). The dictionary object is a kind of selector:

A mapping object maps hashable values to arbitrary objects. Mappings are mutable objects. There is currently only one standard mapping type, the dictionary.

Being based on hash indexes, it is much faster in retrieving values. Let’s try to create our selector.

myfruit = "banana"
fruits = {
    "apple": "The fruit is apple",
    "banana": "The fruit is banana",
    "blueberries": "The fruit is berries",
    "raspberries": "The fruit is berries",
    "blue currant": "The fruit is berries",
    "currant": "The fruit is berries"
}
print(fruits.get(myfruit, "The fruit is unknown"))

In this way, we made our switch selector, beautiful and “pythonic”. But still, the exactness but also the similarity of a word is not evaluated.

Can it be improved?

Yes, of course! Let’s now create a function that will act as a selector, as we’ve seen done in Java and C#. There is a python builtin that applies filters. The function is called filter. Apply a function to an iterable. Functions such as terables are python objects and can be assigned as arguments to other functions. Also, our fruit selector (dictionary) is an iterable. We just need a function that evaluates the similarity of the keys.

def FruitSelector(fruit):
    fruits = {
        "apple": "The fruit is apple",
        "banana": "The fruit is banana",
        "blueberries": "The fruit is berries",
        "raspberries": "The fruit is berries",
        "blue currant": "The fruit is berries",
        "currant": "The fruit is berries",
        "default": "The fruit is unknown"
    }
    return dict(filter(lambda key: fruit in key[0], fruits.items()))

FruitSelector('banana')
FruitSelector('anana')

In python, methods of classes and functions are objects of type Callable. Being objects, information can be stored in them. We will transform our selector into a switch, with an added value: the cache of the last selected fruit. In python everything is an object and therefore can be treated as such. If we wanted to abstract our selector even more to make it become a switch in effect, that’s it:

def switch(match, dictionary, default="no match"):
    for key in dictionary.keys():
        if match in key:
            switch.last_match = key
            return dictionary.get(key)
    return default

fruits = {
    "apple": "The fruit is apple",
    "banana": "The fruit is banana",
    "blueberries": "The fruit is berries",
    "raspberries": "The fruit is berries",
    "blue currant": "The fruit is berries",
    "currant": "The fruit is berries"
}

switch('banana', fruits)
switch('anana', fruits)
switch(switch.last_match, fruits, default="The fruit is unknown")

A callable switch

Also, since functions in python are objects, it is possible to replace string values of the dictionary with functions and return them if the keys match, in this way, can be called. A very simple example. In effect, that’s it:

def switch(match, dictionary, default="no match"):
    for key in dictionary.keys():
        if match in key:
            switch.last_match = key
            return dictionary.get(key)
    return default

calc = {
    "plus": lambda x, y: x + y,
    "minus": lambda x, y: x - y
}

plus = switch('plus', calc, default="unintended function")
minus = switch('minus', calc, default="unintended function")

plus(6, 4)
minus(6, 4)

Conclusion

In fact, python doesn’t need a switch statement. Do other programming languages really need it? I believe that in simple languages like bash, there is a real need for this construct. In Java you could do the same thing I did in python via a map object and same thing in C#. Finally, I agree with the conclusions of PEP 3103: “In the mean time, Python is fine without a switch statement, and perhaps those who claim it would be a mistake to add one are right."