Look at the Python website documentation whatsNew, Python 3.10 is getting closer and closer, so let’s take a look at how Python 3.10 compares to Python 3.9

New features

Multiple context managers are organized by parentheses

** ** ** ** ** ** ** ** ** ** ** *

with open("read.txt"."r") as rfile:
  with open("write.txt"."w") as wfile:
    wfile.write(rfile.read())
Copy the code

Will it come to this, [facepalm][facepalm][facepalm]

So in Python3.10, we can write:

with (
  open("read.txt"."r") as rfile,
  open("write.txt"."w") as wfile
):
    wfile.write(rfile.read())
Copy the code

More friendly error messages

Grammar mistakes

  1. In the codeBrackets or quotes are not closedThe interpreter can provide the exact starting position of the error

For example, the following error code (because the braces are not closed) :

# filename: syntax_error_1.py
expected = {9: 1.18: 2.19: 2.27: 3.28: 3.29: 3.36: 4.37: 4.38: 4.39: 4.45: 5.46: 5.47: 5.48: 5.49: 5.54: 6,
some_other_code = foo()
Copy the code

Python 3.9 runtime error message, difficult to locate the cause of the error:

>C: \ Users \ zioyi \. Pyenv \ pyenv - win \ versions \ 3.9.6 \ python exe syntax_error_1. Py
  File "C:\Users\zioyi\python_code\syntax_error_1.py", line 3
    some_other_code = foo()
                    ^
SyntaxError: invalid syntax
Copy the code

Python 3.10’s error message is much nicer:

>C: \ Users \ zioyi \. Pyenv \ pyenv - win \ versions \ 3.10.0 b4 \ python exe syntax_error_1. Py
  File "C:\Users\zioyi\python_code\syntax_error_1.py", line 1
    expected = {9: 1, 18: 2, 19: 2, 27: 3, 28: 3, 29: 3, 36: 4, 37: 4,
               ^
SyntaxError: '{' was never closed
Copy the code
  1. For syntax errors, the interpreter willThe highlightedDisplays the full range of errors that constitute syntax error codes

First look at Python 3.9:

>>> foo(x, z for z in range(10), t, w)
  File "<stdin>", line 1
    foo(x, z for z in range(10), t, w)
           ^
SyntaxError: Generator expression must be parenthesized
Copy the code

Look again at Python 3.10:

>>> foo(x, z for z in range(10), t, w)
  File "<stdin>", line 1
    foo(x, z for z in range(10), t, w)
           ^^^^^^^^^^^^^^^^^^^^
SyntaxError: Generator expression must be parenthesized
Copy the code

3. Error messages become more intelligent, not just ruthless judges who return SyntaxError: invalid syntax, but more like a teaching teacher

Let’s see what the teacher (Pyhton 3.10) tells us when we make mistakes

>>> # Forget to add colons to conditional statements
>>> if rocket.position > event_horizon
  File "<stdin>", line 1
    if rocket.position > event_horizon
                                      ^
SyntaxError: expected ':'

>>> # Unpack tuples without parentheses
>>> {x,y for x,y in zip('abcd'.'1234')}
  File "<stdin>", line 1
    {x,y for x,y in zip('abcd'.'1234')}
     ^
SyntaxError: did you forget parentheses around the comprehension target?

>>> # When constructing a dictionary, there is no comma between two elements
>>> items = {
.x: 1..y: 2
.z: 3,
  File "<stdin>", line 3
    y: 2
       ^
SyntaxError: invalid syntax. Perhaps you forgot a comma?

>>> # Prepare to replenish multiple exceptions, but write less parentheses
>>> try:
.    build_dyson_sphere()
.except NotEnoughScienceError, NotEnoughResourcesError:
  File "<stdin>", line 3
    except NotEnoughScienceError, NotEnoughResourcesError:
           ^
SyntaxError: multiple exception types must be parenthesized
Copy the code

IndentationErrors

Indenting errors now have more context information about the type of block to be indented, including the position 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
Copy the code

AttributeErrors

When a familiar error occurs, the PyErr_Display function will guess what you like and print out the property you might want:

>>> collections.namedtoplo
Traceback (most recent call last):
  File "<stdin>", line 1.in <module>
AttributeError: module 'collections' has no attribute 'namedtoplo'. Did you mean: namedtuple?
Copy the code

NameErrors

As with property errors, when a naming error occurs, PyErr_Display will guess what you like and print out the variable name you might want:

>>> schwarzschild_black_hole = None
>>> schwarschild_black_hole
Traceback (most recent call last):
  File "<stdin>", line 1.in <module>
NameError: name 'schwarschild_black_hole' is not defined. Did you mean: schwarzschild_black_hole?
Copy the code

PyErr_Display is a really sensible function

switch-caseMatch-case is finally here

Others (Java, Golang, C) have it, you (Pyhton) will have it, and only better! In response to the outcry, the Python version of Switch-Case, or Match-case, has finally arrived, and is one of the most notable features in Python 3.10

grammar

In the Python version of switch-Case, you write it in this format:

match subject:
    case <pattern_1>:
        <action_1>
    case <pattern_2>:
        <action_2>
    case <pattern_3>:
        <action_3>
    case _:
        <action_wildcard>
Copy the code

Simple matching

Before we had match-case, we wrote:

def http_error_if_else(status) :
  if status == 400:
    return "Bad request"
  elif status == 404:
    return "Not found"
  elif status == 418:
    return "I'm a teapot"
  else:
    return "Something's wrong with the internet"
# or so
def http_error_dict(status) :
  http_status_to_error = {
    400: "Bad request".404: "Not found".418: "I'm a teapot"
  }
  return http_status_to_error.get(status, "Something's wrong with the internet")
Copy the code

We know that if-else is not as good in terms of performance and readability as switch-case. Looking at Python 3.10, we can write:

def http_error_match_case(status) :
    match status:
        case 400:
            return "Bad request"
        case 404:
            return "Not found"
        case 418:
            return "I'm a teapot"
        case _:
            return "Something's wrong with the internet"
Copy the code

That’s a lot easier

You can also at the back of the case by using | series multiple, like this:

case 401 | 403 | 404:
    return "Not allowed"
Copy the code

If you do not use _ pocket in a case statement, there may be no match. If no match exists, the behavior is an empty operation. For example, if state 500 is passed, a null operation occurs.

Match both variables and constants

When matching, the subject is transformed according to the pattern after the case to bind variables in pattern. In this example, a data point can be unpacked into its x and y coordinates:

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