Rodrigo πŸπŸš€ Profile picture
Take your Python 🐍 skills to the next level πŸš€!

Sep 26, 2021, 23 tweets

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.

Keep scrolling