(Piro4d via Pixabay)

A switch-case statement is a flow control method that is common to many programming languages. It allows programmers to take actions depending on the state of a variable. By design, Python does not support switch-case statements, but we can write our own.

In this article, we’ll explore three methods for writing our own switch-case statements in Python. We’ll look at one solution that uses dictionaries, another that uses classes, and a third that uses if-elif-else. At the end, we’ll compare the three and see which method is fastest.

What Is a Switch-Case Statement?

In programming languages, a switch-case statement is an expression that evaluates a variable and performs an action based on the variable’s value. We typically use switch-case to evaluate a string and perform an action based on what’s stored in the string. 

For example, we might store the status of an action we’re trying to perform in a string. If the string’s value is INITIALIZING, we’ll perform initialization logic. If the value is EXITING, we’ll perform exit logic. 

There are many use cases for switch-case statements, but we’ll focus on evaluating a string or integer and returning a value based on its content. 

Python Does Not Support Switch-Case Natively

Many languages, like C++ and Java, support switch-case natively. They have keywords we can use to create switch-case statements. Since Python does not have switch-case keywords, we have to do a little more work to arrive at the same result. We’ll need to write our own implementation of switch-case.

Our switch-case implementations will be similar to each other in a few ways. Each will take an argument called case. We’ll write handler functions, or handlers, unique to every case. We’ll also need to handle invalid cases by printing out an Invalid case message.

Writing Our Own Implementation

There are many ways to implement switch-case in Python, but we’re going to focus on three. We’ll build a switch-case statement using dictionaries, another using classes, and a third using an if-elif-else chain. Let’s start by building a switch-case statement using a Python class. 

Building a Switch-Case Statement With a Python Class

One way we can implement switch-case in Python is with a class. We’ll write a class that contains a switch() function and handler functions for every possible case. Then we’ll use getattr() to call the proper handler based on the case.   

Let’s start by creating the switch-case class and defining the switch() function:

class switch_case_class:
  def switch(self, case):
     return getattr(self, case, lambda: "Invalid case")()

In the code above, we’ve created a new class and defined a switch() function with two arguments. Python requires the first argument in any class function to be self, which refers back to our class. The second argument is the case we need to handle. Our switch function makes a single call to getattr() and returns the value. 

getattr() is a built-in Python function that returns an object based on the arguments we pass. The first argument specifies the namespace of the object. The second argument specifies the name of the object that will be returned. The final argument is a Python lambda function that defines the default response should getattr() fail.

Since we’re passing self as the first argument, getattr() searches our class for an object matching the value in case, and returns the lambda expression if it cannot be found. As long as case matches the name of a valid member function, getattr() will call the member function and return its value. 

The next step is defining a few member functions in our new class that will match the cases we’d like to handle. Let’s do that now, below our switch() function:

def INITIALIZING(self):
     return "The program is initializing..."
  def LOADING(self):
     return "The program is loading..."
  def QUITTING(self):
     return "The program is quitting..."

In the example above, we’re defining functions to match a few program states. Maybe we’d like our program to detect when it’s initializing, loading, or quitting, and execute some logic in each case. We’ll simulate that by returning a string.

The final step is to instantiate a new instance of our class, assign a value to our test case, and attempt to use our class to perform a switch-case operation. Let’s write that code below our new class definition:

switch_case = switch_case_class()
test_case = "INITIALIZING"
 
result = switch_case.switch(test_case)
print(result)

We’ve created a new instance of our class called switch_case, along with a test_case. We’ll use our switch() member function to evaluate the test_case and execute our switch-case implementation, then print the results: 

The initialization logic fires and we print the string from the handler function. Let’s test an invalid case in the same way, and make sure we get the error message we expect:

switch_case = switch_case_class()
test_case = "ERROR"
 
result = switch_case.switch(test_case)
print(result)

The code above assigns an invalid value to test_case, and upon running it we expect to see the error message defined in getattr():

Since valid and invalid cases are both evaluated properly, we can call this implementation of switch-case in Python a success. Next, let’s try to create switch-case using a Python dictionary instead of a class. 

Building a Switch-Case Statement With a Python Dictionary

Python dictionaries contain objects in key-value pairs, and since a function is an object we can use a dictionary to create a switch-case statement. In this example, the key will be the case we’re evaluating and the value will be a reference to a handler function.

Let’s start by writing the handler functions for our switch-case statement. In this example, we’ll evaluate a number, so we’ll write a few handlers that return a string based on the number that was passed:

def zero():
  return "Case zero"
def one():
  return "Case one"
def two():
  return "Case two"

Next, we create a dictionary with the case numbers as keys and our handler functions as values:

switch_case_dict = {
  0: zero(),
  1: one(),
  2: two()
}

Finally, we’ll use the Python dictionary’s get() member function as a substitute for switch-case. It will search for a key to match the case we pass, and execute the associated handler function. We also pass a lambda expression to get() as a fallback if the case cannot be found in the dictionary:

test_case = 2
 
result = switch_case_dict.get(test_case, lambda: "Invalid case")
 
print(result)

After we execute our code, Python evaluates our switch-case statement and prints the expected output:

Let’s also try to use our switch-case dictionary with an invalid case, like we did in the previous example with classes. Here’s the code we’ll use:

case = 200
 
result = switch_case_dict.get(case, lambda: "Invalid case")
 
print(result)

Since we did not write a handler for 200, we expect to see an Invalid case message:

Our error message works as expected, and we’ve finished implementing switch-case with a Python dictionary. 

Let’s go over our third and final solution, and build switch-case functionality by chaining together if-elif-else statements in a function.

Building a Switch-Case by Chaining If-Elif-Else

Let’s explore using chained if-elif-else statements to implement switch-case in Python. We’ll build our statements in a function that takes a single argument, which is the case that we’d like to handle. The body of the function will contain our case handling logic.

In contrast to our earlier examples, we do not need to define a new function for each handler. This time we’ll handle each case in its respective if-elif-else block. Here’s the code:

def switch_case_if_else(case):
  if case == "CASE_1":
     return 1
  elif case == "CASE_2":
     return 2
  elif case == "CASE_3":
     return 3
  else:
     return "Invalid case"

Our function contains nothing more than an if-elif-else chain of statements, with the error condition in the final else statement. The case that is passed as an argument will be compared to each statement in turn, until it finally hits the proper handler and Python returns a value. 

We’ll test this version of switch-case by creating a test case, calling our switch-case function, and storing the results:

test_case = "CASE_2"
 
result = switch_case_if_else(test_case)
 
print(f"Our case is {test_case} and the result was {result}")

Once the switch-case statement executes, we print the result:

Python returns the expected result for our case, so we know our switch-case implementation is working. We can also check that our code is handling invalid cases properly by passing an invalid case:

test_case = "CASE_8"
 
result = switch_case_if_else(test_case)
 
print(f"Our case is {test_case} and the result was {result}")

When we run the code above, we see that the else statement is acting like a catch-all and returning Invalid case when a given case cannot be found:

Let’s now determine which of the methods we used is fastest. We’ll measure the time it takes to run a switch-case operation for each of our three implementations, then compare them. 

Comparing Our Switch-Case Methods

Now that we’ve implemented switch-case in Python using three different methods, we can test them to see which solution is optimal. Let’s evaluate our code based on the execution time for each solution. 

To learn more about using timeit to measure the speed of your software, take a look at our article on benchmarking Python execution time.

Setting Up timeit

We’ll start our testing by importing timeit and setting two variables with the test parameters. We’ll test each switch-case statement 100,000 times, and repeat each test 10 times. That will give us one million executions of each switch-case statement.

We’ll also need to implement a function to average the test results for each switch-case implementation. Since timeit outputs the results in a list, we’ll divide the sum of each list by the length of the list, and that will give us an average time for our tests. Here’s the code we’ll use:

import timeit
 
test_count = 100000
repeat_count = 10
 
def average(list):
  return sum(list) / len(list)

Below that code we’ll need to set two variables for each switch-case implementation. One will contain the setup code. In a nutshell, this is the code timeit will execute before running our tests. We’ll store our test code in a long multiline string.

We’ll need another variable to store the execution logic of each switch-case statement. If you look closely, you can see that both variables are the code we wrote in our previous examples. 

setup_switch_case_dict = '''
def zero():
  return "Case zero"
def one():
  return "Case one"
def two():
  return "Case two"
 
switch_case_dict = {
  0: zero(),
  1: one(),
  2: two()
}
 
test_case = 2
'''
 
execute_switch_case_dict = 'switch_case_dict.get(test_case, lambda: "Invalid case")'

Once we have the setup and execution variables created for each switch-case implementation, we’ll run the tests using timeit.repeat(). The function takes four arguments: the code we’re executing, the setup code, the amount of times we’ll repeat the test, and the number of times we’ll run each test. 

Here’s the code for our switch-case dictionary implementation:

result = timeit.repeat(
  execute_switch_case_dict,
  setup_switch_case_dict,
  repeat=repeat_count,
  number=test_count)
 
print(f"The average execution time for switch_case_dict is: {average(result)} seconds")

We’ll repeat the same steps for each switch-case implementation we’re testing. 

The Fastest Way to Switch-Case In Python

Now that our tests have been set up, we’ll run our script and print the results:

Our switch-case implementation based on Python dictionaries is hands-down the fastest. It’s roughly 30% faster than the if-elif-else chain, and more than twice as fast as our class-based solution. 

The timing will vary depending on your computer’s speed, but using a dictionary to implement switch-case in Python is the fastest method of the three.

Learn Switch-Case and More With Udacity

In this article, you learned three methods for implementing switch-case in Python. Though the language does not support switch-case natively, it gives you the tools you need to create switch-case statements yourself. 

To continue learning the nuances of Python, enroll in our Introduction to Programming Nanodegree. Our expert-designed program will take you through the basics of programming and will teach you to think and problem-solve like a programmer.