Replacements for switch statement in Python?
The original answer below was written in 2008. Since then, Python 3.10 (2021) introduced the match
-case
statement which provides a first-class implementation of a "switch" for Python. For example:
def f(x):
match x:
case 'a':
return 1
case 'b':
return 2
case _:
return 0 # 0 is the default case if x is not found
The match
-case
statement is considerably more powerful than this simple example.
You could use a dictionary:
def f(x):
return {
'a': 1,
'b': 2,
}[x]
What is the syntactical equivalent to switch/case in Python?
TL;DR
As of Python 3.10.0 (alpha6 released March 30, 2021), Python has an official syntactical equivalent called match
.
The basic syntax is:
match value:
case condition:
action(s)
...
For older Python versions, there are only workarounds if you don't want to resort to if
-elif
-else
.
See this excellent community post for a collection of some.
Example
my_value = 10
match my_value:
case 10:
print("The number is ten")
case 2*10:
print("The number is the double of ten")
case 100:
print("The number is one hundred")
case _:
# this is the default handler if none
# of the above cases match.
print("The number is none of 10, 2*10 or 100")
Therefore, other answers involving workarounds aren't valid anymore - also from a performance point of view.
Important Notices
If coming from languages which support switch
and case
, it's likely that you already know about their behavior. With Python, there are some differences to note though.
Cases don't fall through
It's common that languages with
switch
-case
statements execute every case the value matches - from top to bottom. Hence, there is a third statement -break
- to be used inswitch
-case
constructs if you don't want to fall through:value = 10
switch (value) {
case 10:
print("Value is ten");
case 2*5:
print("Value is the double of five");
break;
case 20/2:
print("Value is the half of twenty");
default:
print("This is just the default action.");
}In this example, the first two cases would be executed because the first case falls through. If there was no
break
statement inside the second case, all cases, including the default one, would be executed.In Python, only the first matching case is being executed. You can think of it like every case would contain a hidden
break
statement.Variable references don't work as a condition
base_color = "red"
chosen_color = "green"
match chosen_color:
case base_color:
print("Yes, it matches!")This code does actually print that the colors match!
Bare variable references as case conditions will always match.
Regardless, literals like
case "red": ...
and qualified (i.e. dotted) names likecase AllColors.red
work like expected - no need to be scared of them.All of this is the case, because the Python Software Foundation did not decide to just copy another boring control flow model, but to actually implement a fully-fledged pattern matcher which is more than just a
switch
-case
statement. More on this can be found in the next section.
Powerful Pattern Matching
match
- Match ain't case hooey
Specification and information provided in the Python Enhancement Proposals (PEP) nos. 634-636
In Python, match
is actually much more than a simple switch - therefore probably the name. It features special functionality like deep placeholders and wildcards.
Examples inspired by reading the documentation - so you don't have to:
match point:
case (0, 0):
print("Origin")
case (0, y):
print("Our current Y position is", y, " now.")
You can match arbitrary nested data structures, including placeholders. In the above example, we are matching a tuple with two items where in the second case, we use a placeholder y
that gets its value assigned upon matching.
You can also match class attributes, in a very similar fashion:
class Point:
x: int
y: int
def location(point):
match point:
case Point(x=0, y=0):
print("Origin is the point's location.")
case Point(x=0, y=y):
print("The point lies on the y axis at a height of", y, "units.")
This also explains why you can't match single variable references in case conditions: you don't actually match against the value of that variable but actually introduce a placeholder of that same name!
Therefore, if you were going to print chosen_color
like this:
base_color = "red"
chosen_color = "green"
match chosen_color:
case base_color:
print("Our base color is", base_color)
It would actually print out
Our base color is green
because the base_color
is now a placeholder which gets assigned the value of our chosen_color
.
There are a lot more use cases for this advanced pattern matching, an interesting couple of them mentioned in the Python documentation.
Epilogue
It will take its time until Python 3.10 gets its deserved adoption. Python 3.10.0 is set to be released stable on October 4, 2021 - meaning it might be included in Ubuntu 22.04 and up.
If you just want to play around and write programs for yourself, deploy them to your own server, or if you intend to distribute your creations in packaged form and not as plain source code files, give this new feature already a try in your programs - it's going to be a benefit!
Addendum
Trying Python 3.10.0
For Windows and macOS users, this page features the official installer downloads.
On Debian and Ubuntu, you can use the very popular "DeadSnakes"-project PPA:
sudo add-apt-repository ppa:deadsnakes/ppa
sudo apt update
sudo apt install python3.10
python3.10 --version
Trying Python 3.10.0 without destroying your system
Docker is an option for using Python 3.10 without any complicated setup steps and in a completely isolated environment.
docker run -it python:3.10.0a6-alpine
And that's it. As the time passes by, new alpha or beta versions might be released. You will want to replace the a6
with a different version then.
Replacements for switch statement in Python?
The original answer below was written in 2008. Since then, Python 3.10 (2021) introduced the match
-case
statement which provides a first-class implementation of a "switch" for Python. For example:
def f(x):
match x:
case 'a':
return 1
case 'b':
return 2
case _:
return 0 # 0 is the default case if x is not found
The match
-case
statement is considerably more powerful than this simple example.
You could use a dictionary:
def f(x):
return {
'a': 1,
'b': 2,
}[x]
Replacements for switch statement in Python?
The original answer below was written in 2008. Since then, Python 3.10 (2021) introduced the match
-case
statement which provides a first-class implementation of a "switch" for Python. For example:
def f(x):
match x:
case 'a':
return 1
case 'b':
return 2
case _:
return 0 # 0 is the default case if x is not found
The match
-case
statement is considerably more powerful than this simple example.
You could use a dictionary:
def f(x):
return {
'a': 1,
'b': 2,
}[x]
Python Switch/Case Statement Adaptation
I see a lot of repetition in your code, so the first thing I'll think of would be: "can I use a loop to simply this code?" and the answer is yes!
Since your code repeatedly used the six subjectTypes
and the keySubject
depends on the subject type, creating a list of the six types then use next()
with a generator expression should simplify the over abundance of if
's (If there weren't any correlations, a dictionary would work instead). Also, instead of array_data
, you can use an if-elif-else
clause to prevent an extra block level.
sampleKeys = [...]
key = random.choice(sampleKeys)
subjectTypes = ['transaction_recipient_notification', 'transaction_recipient_authentication',
'transaction_recipient_verification', 'transaction_account_verification',
'transaction_account_tokenization', 'transaction_recipient_payment']
if '_issuers' in key:
keySubject = next(t + '_issuers' for t in subjectTypes if t in key)
elif '_field_results' in key:
keySubject = next(t + '_field_results' for t in subjectTypes if t in key)
else:
keySubject = next(t for t in subjectTypes if t in key)
print(f'BEFORE ===> {key}')
print(f'AFTER ===> {keySubject}')
Python replacement of switch case into dictionary (for function calls)
You are calling all of the functions (without await) when defining the dictionary and storing their return values in the dictionary instead of references to the functions.
async def reminder(self, ctx, *args):
reminder_operations = {
'add': self.reminder_add,
'modify': self.reminder_modify,
'delete': self.reminder_delete,
'deleteall': self.reminder_delete_all
}
return await reminder_operations[args[0]](ctx)
Switch/Case Matlab. What is the Python equivalent?
Python has no switch statement so you have to use if/else
if nmax == 0: # this is equal to your case 0
# do something
elif nmax == 1: # this is equal to your case 1
# do something
else: # this is equal to your otherwise case
# do something
Related Topics
Converting Epoch Time With Milliseconds to Datetime
Why Is Using 'Eval' a Bad Practice
Is There a Built in Function For String Natural Sort
What Is the Purpose of the Single Underscore "_" Variable in Python
How to Concatenate Items in a List to a Single String
Tkinter Creating Buttons in For Loop Passing Command Arguments
What Is the Purpose and Use of **Kwargs
Tkinter Understanding Mainloop
Check If a Given Key Already Exists in a Dictionary
Integer Division by Negative Number
Flatten an Irregular List of Lists
Selenium "Selenium.Common.Exceptions.Nosuchelementexception" When Using Chrome
How to Parse an Iso 8601-Formatted Date
How to Print Curly-Brace Characters in a String While Using .Format
Error "Microsoft Visual C++ 14.0 Is Required (Unable to Find Vcvarsall.Bat)"