What's New in Python 3.10 – The Most Important Features and Changes
Python has long held key positions on the most popular programming languages list. It currently ranks first in the TIOBE Index for July 2022 & PYPL Popularity of Programming Language, ahead of Java, JS, and C/C++. This article will discuss the most important new features in Python 3.10 that have appeared in recent years and why you should switch to them.
Changes in Python 3.8 vs 3.7
Release Date: October 2019
Self-documenting expressions and debugging for f-strings
We will recall how with Python 3.6, users got an excellent opportunity to format strings using the .format() method and the f prefix before the line and {} to place data inside the expression. Often we needed to name what we were deriving to add specifics.
Example Python <3.8
Since version 3.8, users can create lines for self-documenting expressions and debugging. It has become even easier to do this. We add the symbol `=` inside the {} and get the same result.
Example Python 3.8 feature
New walrus `:=` operator
We can directly perform two actions in a condition, a loop, or something else: assign a value to a variable and then compare the expression. Let's give an example of a simple console application that displays everything the user enters, as long as the line is not empty.
Example Python <3.8
Here we assign the result of user input twice: before the loop and in its body. Now we have a way to immediately save the outcome of the execution when checking the condition:
Example Python 3.8 feature
As you can see, we follow the same steps: first, we assign a value to the user_input variable, then perform the validation. If it works, we go into the loop and output the updated content of user_input until the user input is empty.
What about using the user_input variable later in the code, after the loop? Let's explore a situation where we create two variables using the walrus operator:
Example Python 3.8 feature
Let's try to output the value outside the conditional statement:
Example Python 3.8 feature
However, you should notice that Python will reject any of those values and check if the first operand is False. So, `n` will always be created, but `first_company` will only be made when the expression `n == 1` or the next `n > 1` is executed.
Example Python 3.8 feature
As we can see, n also exists after the body of the conditional statement if, when first_company was not initialized, so we got the NameError: name 'first_company' is not defined.
This approach makes it possible to create more concise designs, but the main thing is not to mess around too much. 😀
Ability to specify positional-only arguments
Here is an explanation from the official documentation:
Now users can limit parameters that must pass positionally and cannot be passed as a keyword, positional, positional or keyword, only keyword, to some functions.
Example Python 3.8 feature
Let's explore an example of built-in functions where we should not transfer keywords but only positional parameters.
Example Python 3.8 feature
We cannot pass keywords 'a, b' arguments to the divmod function. Likewise with len(), where we pass only positional arguments:
Example Python 3.8 feature
You might ask: how to transfer args/kwargs in this case? Well, here's the solution:
Example Python 3.8 feature
DictReader returns a simple dict instead of an OrderedDict
With Python 3.7, we got guaranteed ordered dicts, which covered all the possible advantages of collections.OrderedDict used to have over dict. So we got a logical change of return result in the csv module. If previously DictReader necessarily returned a list of OrderedDicts:
Example Python <3.8
Now, since Python 3.7 no longer makes sense, the result is currently not an OrderedDict, but a simple dict.
Example Python 3.8 feature
Changes in Python 3.9 vs 3.8
Release Date: October 2020
Ability to use | (ior) from dict
Using | for dict! Now we have the possibility to use | (ior) also with dict. Merging when using |, and updating when using |= as an assignment operator.
Example Python 3.9 feature
And
Example Python 3.9 feature
Type hinting using built-in collections types
Now you don't need to import the typing module to add typing to lists, dicts, sets, and other built-in classes.
Example Python 3.9 feature
.removeprefix() and .removesuffix() will override .startswith() or .endswith()
Are you using the .startswith() or .endswith() string methods to match and remove? Users now can do this more easily with the new .removeprefix() and .removesuffix() methods.
Example Python 3.9 feature
Changes in Python 3.10 vs 3.9
Release Date: October 2021
Using the new Union `|` operator
In Python 3.9, we looked at adding built-in collections to type hinting. Among the new features in Python 3.10, we received another improvement - the use of the new Union operator `|`. If previously we were forced to specify all types in Union:
Example Python <3.10
Now we specify the types, breaking one with the other operator '|':
Example Python 3.10 feature
The same applies to Optional because it is a Union[Type, None].
Example Python <3.10
Example Python 3.10 feature
It may be noted that mypy supports PEP-604.
Ability to use context managers with parentheses
The change will help to split several collections that users pass to the context manager into several lines:
Example Python 3.10 feature
Now it looks a lot nicer than single-line iterating across commas. Note that the trailing comma is supported.
Structural pattern matching
We will not discuss the historical component; let's just say that this Python 3.10 breaking change came to us from many other languages, for example, Haskell, Scala, Rust and so on. We need to immediately note that pattern matching should not be confused with a simple Match Case because it is not just a switch statement like in C++. Pattern matching here acts as a verification mechanism and helps with data unpacking and managing the execution flow.
Syntax:
Example Python 3.10 feature
It is often necessary to build structures like this one:
Example Python <3.10
Someone might say that it is possible to write it shorter, for example by separating the list of beginners into a list/tuple - OK:
Example Python <3.10
However, now we can do it more easily:
Example Python 3.10 feature
As you can see, we have the option to use | ("or"), and instead of "default", we use _ (wildcard). It will work if all other cases above do not work. Note that after this block, we cannot use other cases. Otherwise, we will receive a SyntaxError: wildcard makes remaining patterns unreachable error.
Example Python 3.10 feature
Will they continue to write like this in the future? We will find out in the coming years because whether they choose to use old or new records will ultimately depend on the users.
But wait, there's more! 😀
Sometimes, users not only check for equality for some reason but want to check whether the input data is a list or a tuple. In this case, the annotation is not enough. It only assists with static analysis through linters, development environments, or mypy. Anything can still get into the input of such a function. After successful validation, we want to extract and use the value in the body of the condition:
Example Python <3.10
This is how we did checking and unpacking in previous versions, but why leave it this way if pattern matching allows you to do two things at once:
Example Python 3.10 feature
Elegant, isn't it? You can think of many use cases; one of them could be using pattern matching with classes. Let's explore an example.
Let's describe the classes, Vector2D and Vector3D:
Example Python 3.10 feature
Let's create a function that accepts an instance of the Vector2D or Vector3D class as a matcher and displays information about them otherwise, we will display "Another vector":
Example Python 3.10 feature
As you can see, the entries are very similar to calling Vector2D or Vector3D constructors, but you need to understand that the matcher does not call constructors. Verification takes place by comparing the parameters. We can even check exclusively for x=0 when creating such an instance would result in a TypeError:
Example Python 3.10 feature
We will leave you the opportunity to experiment and find your ways of using this new Python 3.10 feature. However, we are sure that this operator will be frequently used due to its conciseness and multifunctionality, provided it is used correctly.
Key takeaways
Modern market dynamics require constantly updating knowledge and quickly responding to new trends. We are confident that new functionality in Python 3.10 will update the best-practice list soon, which means that you, as a specialist, will be able to speed up the development and maintenance of your code. So, if you haven’t read what’s new in Python 3.11, we’d recommend you do that, as there we’re talking about moving from Python 3.10 to Python 3.11.
Thanks for reading. Glory to Ukraine 🇺🇦