Have you heard that Python π 3.10 will be released soon?
Are you ready for when it drops π£π₯?
Python 3.10 will ship with the new β¨ match statement, and I created a cheatsheet just for that.
This is also a thread π𧡠that breaks it down and explains everything:
The cheatsheet is free and teaches you 12+ things about the new `match` statement.
From the basics, to object destructuring, to wildcards, among other things.
Get it from the link π, and keep reading below to learn all about the `match` statement.
mathspp.gumroad.com/l/cheatsheet_mβ¦
In its most basic form, a `match` statement kind of resembles an `if` statement.
That's what most of the βswitchβ or βmatchβ statements in other languages do: a series of `if` / `elif` / `else` statements.
Even a basic `case` is powerful: use `|` to separate multiple options.
In Python, the `case` statement can be followed by an `if` statement.
This `if` statement can be used to add more restrictions on top of what the `case` catches.
In the `factorial` example below, we use it to make sure we only compute the factorial of positive numbers.
But... The `match` statement has a greater purpose!
The `match` statement was born to MATCH STRUCTURE of objects.
For example, a colour can be thought of as a name, plus the RGB values, plus an alpha channel for transparency.
How can we shape things into that structure?
The code above is doing PLENTY of things!
In such a little amount of code!
It accepts a `colour`, and tries its best to put it into the (name, (r, g, b, a)) format of the `return` statement.
In order to do so, it will give default values to missing pieces of information.
For example, the first `case` statement deals with this scenario:
We only receive RGB values.
If we only get RGB values, we create the default colour name (an empty string) and the default transparency value (0).
Here are some example calls:
Another cool thing is that you can give names to sub-patterns.
This is useful, for example, when you expect part of the structure to always remain the same...
... but you need to deal with a portion that changes:
But there is MORE!
The `match` statement knows how to do βobject destructuringβ.
This means that the `match` statement can match objects depending on the values of their attributes!
Isn't that insane?!
For example, imagine you have a 2D point:
We can create a `case` statement that only matches points with specific `x` and `y` values.
Or with a specific `x` value and a generic `y` value.
Or the other way around.
Here are some examples:
Now, if you are ANYTHING like me...
You are lazy!
That's fine, programmers should be βlazy smartβ.
Typing `x=` and `y=` in all the `case`s is boring and error-prone.
That's why the Python π Gods invented `__match_args__`:
Use it and say goodbye to `x=` and `y=` everywhere!
This was object destructuring done with custom classes...
But it can also be done with built-in types!
And when that is the case, it can act as a basic form of type validation!
Here is the colour example from before, but now ensuring everything has the correct type:
If we run the code above, we prevent all sorts of trouble if the things aren't what they should be!
Below, we trigger the `ValueError` by trying to use all sorts of funky stuff instead of the expected data types.
(Sure, maybe we could be lenient about the 26.0 π)
After knowing all about object destructuring, I think it's cool to talk about wildcards.
There are two wildcards: `*` and `**`.
`*` is to be used with iterators (like lists and tuples).
It's also related to the `*args` idiom and unpacking with assignments:
The `**` wildcard is for dicts.
But first, here's something that might throw you off:
β When a `case` statement includes specific keys (or key/value pairs), it doesn't try to check if that's the _whole_ dictionary.
It only checks if that portion is inside the given dict.
So, with that out of the way, it is safe to tell you that `**` matches an arbitrary portion of a dictionary.
Of course, that portion may or may not be empty.
(Much like the `*` wildcard can match an empty iterator.)
So, there's a nice combo you can make here, if you use the `**` wildcard and the `if` statements inside the `case` statements.
What's that?
You can write a neat `case` that checks if a given dictionary has the exact structure you are interested in:
This was a breakdown of the cheatsheet you saw in the beginning, which you can get for free π
mathspp.gumroad.com/l/cheatsheet_mβ¦
The cheatsheet, in turn, was a summary of my most popular blog article: π mathspp.com/blog/pydonts/sβ¦
If you want to learn more about the `match` statement":
I have a great article explaining when the `match` statement ISN'T the right tool for the job: π mathspp.com/blog/pydonts/sβ¦
That's it for now!
Do you want to level up your Python π game?
Want to get awesome Python π knowledge and content daily?
Then follow @mathsppblog because that is exactly what I do here on Twitter.
Also, if you found value in this thread, show your love π and retweet it π
Here's a TL;DR
1. `match` declares what object we are looking at;
2. `case` defines the cases we want to handle;
3. `|` separates multiple options;
4. use `if`s after `case`s to refine conditions;
5. use `_` to match any object at all (kind of like an `else`);
6. object destructuring works on custom classes;
7. object destructuring gives access to objects' attributes;
8. __match_args__ allows to remove boilerplate from `case`s;
9. object destructuring on built-ins works like basic type validation;
10. sub-patterns can be named;
11. use `*` with iters to match arbitrary sections;
12. `case` with dict don't check full structure;
13. `case` with dict can check just key or key/value pairs.
14. use `**` to match arbitrary portion of dict; and
15. use `**` with `if` to enforce specific dict structure.
Bye π
Share this Scrolly Tale with your friends.
A Scrolly Tale is a new way to read Twitter threads with a more visually immersive experience.
Discover more beautiful Scrolly Tales like this.