Patrick Loeber

Patrick Loeber

New Features In Python 3.10 You Should Know

New Features In Python 3.10 You Should Know

What's new in Python 3.10?

This article shows and explains the most important new features in Python 3.10. The release is expected to be on 2021-10-04 (see Python 3.10 Release Schedule).

Overview

Before we dive into the details, here's a brief summary of the most important changes:

  • Structural Pattern Matching (New syntax feature)
  • Parenthesized context managers (New syntax feature)
  • New optional strict argument for zip() to ensure same length
  • Better error messages and interpreter improvements
  • Allow writing union types as X | Y (New typing feature)
  • Explicit Type Aliases (New typing feature)
  • Require OpenSSL 1.1.1 or newer
  • Deprecate distutils module
  • Constructors str(), bytes(), and bytearray() are now faster
  • Faster python startup time through fewer imports

Structural Pattern Matching

Structural Pattern Matching lets you match variables against a set of different possible values (like the switch/case in other languages). But it also allows to match against patterns of values, e.g., an object with a certain property set to a specific value.

Structural pattern matching has been added in the form of a match statement and case statements of patterns with associated actions.

Syntax:

match subject:
    case <pattern_1>:
        <action_1>
    case <pattern_2>:
        <action_2>
    case _:
        <action_wildcard>

Example:

def http_error(status):
    match status:
        case 400:
            return "Bad request"
        case 401 | 403:
            return "Not allowed"
        case 404:
            return "Not found"
          case 418:
            return "I'm a teapot"
        case _:
            return "Something's wrong with the internet"

Notice how you can combine several literals in a single pattern using | ("or").

Without the use of _ in a case statement, a match may not exist. If no match exists, the behavior is a no-op. For example, if status of 500 is passed, and _ is not used, the result is None.

In addition, a variable can also be matched against patterns. Patterns can look like unpacking assignments, and a pattern may be used to bind variables:

# point is an (x, y) tuple
match point:
    case (0, 0):
        print("Origin")
    case (0, y):
        print(f"x=0 y={y}")
    case (x, 0):
        print(f"y={x} y=0")
    case (x, y):
        print(f"x={x}, y={y}")
    case _:
        raise ValueError("Not a point")

There are more syntax options available for the pattern matching feature, such as using an additional if statement as guard, or matching for class patterns. A more detailed documentation is available here.

Parenthesized context managers

Using enclosing parentheses for continuation across multiple lines in context managers is now supported. This allows formatting a long collection of context managers in multiple lines:

with (
    CtxManager1() as ctx1,
    CtxManager2() as ctx2
):
    # do something

Optional length-checking to zip()

An optional strict boolean keyword parameter to the built-in zip() method was added. When set to True, a ValueError is raised if one of the arguments is exhausted before the others:

names = ['Max', 'Mary', 'Ben']
ages = [22, 26]

result = zip(names, ages)
print(list(result))
# [('Max', 22), ('Mary', 26)]
# --> By default the zipped elements simply stop when the end
#     of the shorter iterable is reached

result = zip(names, ages, strict=True)

# Error!
Traceback (most recent call last):
  File "example.py", line 4, in <module>
    print(list(result))
ValueError: zip() argument 2 is shorter than argument 1

Better Error messages and Interpreter improvements

Many of the errors messages have been improved — not only delivering more precise information about the error, but also more precise information about where the error actually occurs.

Look at this simple example with a missing parenthesis:

print("Hello"
print("World")

Here’s the Python 3.9 Error. It does not give you a clue at all why and where the error happens:

  File "example.py", line 2
    print("World")
        ^
SyntaxError: invalid syntax

And this is the Python 3.10 Error. You can see the issue immediately:

  File "example.py", line 1
    print("Hello"
         ^
SyntaxError: '(' was never closed

Here are some other examples with an improved error message.

  • Missing : before blocks: "SyntaxError: expected ':'"
  • Missing parenthesis: "SyntaxError: did you forget parentheses around the comprehension target?"
  • Missing commas: "SyntaxError: invalid syntax. Perhaps you forgot a comma?"

Notice how nicely the Python interpreter asks ;)

Furthermore, many IndentationError exceptions now have more context regarding what kind of block was expecting an indentation, including the location of the statement:

def foo():
    if lel:
    x = 2

File "<stdin>", line 3
    x = 2
    ^
IndentationError: expected an indented block after 'if' statement in line 2

More examples of the new error messages can be found here.

In addition to improved Error messages, more precise and reliable line numbers for debugging, profiling and coverage tools are available. Tracing events with the correct line number are generated for all lines of code executed and only for lines of code that are executed.

New typing features

This section covers major changes affecting type hints and the typing module.

Allow writing union types as X | Y

A new type union operator was introduced which enables the syntax X | Y. This provides a cleaner way of expressing "either type X or type Y" instead of using typing.Union:

# old syntax
from typing import Union
def square(number: Union[int, float]) -> Union[int, float]:
    return number ** 2

# new syntax
def square(number: int | float) -> int | float:
    return number ** 2

Additionally, this new syntax is also accepted as the second argument to isinstance() and issubclass():

isinstance(1, int | str)

Explicit Type Aliases

Now the typing module has a special value TypeAlias which lets you declare type aliases more explicitly. This is useful for type checkers to distinguish between type aliases and ordinary assignments:

from typing import TypeAlias
StrCache: TypeAlias = 'Cache[str]'

Parameter Specification Variables

In addition, two new options to improve the information provided to static type checkers have been provided with typing.ParamSpec and typing.Concatenate.

Important updates and deprecations

Require OpenSSL 1.1.1 or newer

Python now requires OpenSSL 1.1.1 or newer. OpenSSL 1.0.2 is no longer supported. This affects the hashlib, hmac, and ssl module and modernizes one of CPython’s key dependencies.

Deprecate distutils module.

The entire distutils package is deprecated, to be removed in Python 3.12. Its functionality for specifying package builds has already been completely replaced by third-party packages setuptools and packaging, and most other commonly used APIs are available elsewhere in the standard library.

No new modules, but many improved ones

No new modules are added, but a lot of modules have been improved. Among them are:

asyncio, argparse, base64, contextlib, dataclasses, hashlib, os, pathlib, pprint, statistics, socket, ssl, sqlite3, threading, traceback, typing, unittest, and xml.

For the full list of improved modules see here.

Optimizations

Multiple optimizations were implemented (see full list). The most important ones are:

  • Constructors str(), bytes(), and bytearray() are now faster (around 30–40% for small objects)
  • The runpy module now imports fewer modules. The python3 -m module-name command startup time is 1.4x faster in average. On Linux, python3 -I -m module-name imports 69 modules on Python 3.9, whereas it only imports 51 modules (-18) on Python 3.10.

Closing thoughts

Python 3.10 brings many great new features, improvements, and optimizations. The most interesting one is certainly the pattern matching feature, which can be useful in various scenarios.

The new error messages are also a great improvement and can save a lot of time when trying to find the mistake. This could be especially helpful for beginners that previously often times only got confused by the error message.

If you like this article, make sure to share it on Twitter and let me know which new feature you like the most :)

Resources

The official article with all new features can be found here:
https://docs.python.org/3.10/whatsnew/3.10.html

 
Share this