© The Author(s), under exclusive license to APress Media, LLC, part of Springer Nature 2022
M. IndenPython Challengeshttps://doi.org/10.1007/978-1-4842-7398-2_14

Short Introduction to Python 3.10

Michael Inden1  
(1)
Zurich, Switzerland
 

This appendix presents some of the enhancements implemented in Python 3.10, which was released in October 2021. Therein are features that may be relevant to you. I start with improvements to error messages. Then I briefly look at match for convenient design and formulation of case distinctions. Finally, I briefly touch on performance improvements as well as type checks and other details.

D.1 Error Messages

Sometimes errors occur in a Python program. Various types of errors can be observed. When creating programs, SyntaxError or IndentationError arise from time to time. These errors can be fixed easily with the context information and accurate line numbers provided by Python. Let’s take a look at two short examples.

D.1.1 Assignment Error Messages

For the sake of demonstrating the improvements in error messages, let’s assume you accidentally specified an assignment (=) instead of a comparison (==) in an if.

Python 3.9.x

With Python 3.9.x, the error is detected, of course, but gets reported rather unspecifically as invalid syntax, as follows:
>>> if x = 6:
  File "<stdin>", line 1
    if x = 6:
         ^
SyntaxError: invalid syntax

Unfortunately, there is no hint of what is wrong with the syntax. Depending on your programming experience, the underlying problem is either quickly found or you are left guessing.

Improvement with Python 3.10

Let’s look at how the error message for the same lines changes with Python version 3.10, in particular becoming much more understandable:
>>> if x = 6:
  File "<stdin>", line 1
    if x = 6:
       ^^^^^
SyntaxError: invalid syntax. Maybe you meant '==' or ':=' instead of '='?

As you can see, not only is the problem’s cause mentioned directly, but two possibilities for remedial action are suggested at once.

D.1.2 Error Messages for Incomplete Strings

Sometimes you might overlook delimiting a string at the beginning or the end with quotation marks. Let’s take a look at the error messages generated by different Python versions.

Python 3.9.x

You define a set with some names, but the last one does not end correctly with a quotation mark.
>>> data = { "Tim", "Tom", "Mike}
  File "<stdin>", line 1
    data = { "Tim", "Tom", "Mike}
                                 ^
SyntaxError: EOL while scanning string literal

Improvement with Python 3.10

With Python 3.10, the problem is directly apparent from the error message, namely the missing quotation mark at the end of the string:
>>> data = { "Tim", "Tom", "Mike}
  File "<stdin>", line 1
    data = { "Tim", "Tom", "Mike}
                        ^
SyntaxError: unterminated string literal (detected at line 1)

D.2 Case Distinctions with match

In many languages, case distinctions may be expressed using the if statement as well as the switch statement. The latter was missing in Python for a long time. With Python 3.10 comes match, an even more powerful variant for case discrimination with which we can now finally also realize the switch statement. In addition, match enables pattern matching, a method that is used in functional languages such as Erlang/Elixir or Scala, but also makes its way into the current Java 17 (in a trimmed-down form).

Let’s look at some possibilities of match again a few examples.

D.2.1 Python 3.9.x

Suppose you want to map HTTP status codes to their meaning. This can be solved with an if cascade as follows (shown here only in excerpts):
http_code = 201
if http_code == 200:
    print("OK")
elif http_code == 201:
    print("CREATED")
elif http_code == 404:
    print("NOT FOUND")
elif http_code == 418:
    print("I AM A TEAPOT")
else:
    print("UNMATCHED CODE")

However, it is noticeable that this is not easy to read.

Improvement with Python 3.10

Let’s look at how much clearer the above construct becomes with the use of match. In particular, with _ you can also include a wildcard case that is jumped to whenever the other cases don’t match.
match http_code:
    case 200:
        print("OK")
    case 201:
        print("CREATED")
    case 404:
        print("NOT FOUND")
    case 418:
        print("I AM A TEAPOT")
    case _:
        print("UNMATCHED CODE")

Combination of Values

By using the pipe operator (|) , it is possible to specify multiple values for which the following action should be executed. This is shown here for Thursday and Friday in combination and Saturday and Sunday:
def get_info(day):
    match day:
        case 'Monday':
            return "I don't like..."
        case 'Thursday' | 'Friday':
            return 'Nearly there!'
        case 'Saturday' | 'Sunday':
            return 'Weekend!!!'
        case _:
            return 'In Between...'

More Complex Matching I

You have just seen that you can specify values with the pipe operator as alternatives. However, it is also possible to check iterables for a match:
values = (2,3,4)
match values:
    case [1,2,3,4]:
        print("4 in a row")
    case [1,2,3] | [2,3,4]:
        print("3 in a row")
    case [1,2,4] | [1,3,4]:
        print("3 but not connected")
    case _:
        print("SINGLE OR DOUBLE")

More Complex Matching II

The capabilities of match are even more powerful, however, which I’ll just hint at here. Please note that you can specify matching patterns and additional conditions after the values in case.
class Gender(Enum):
    MALE = auto()
    FEMALE = auto()
def classify(person):
    match person:
        case (name, age, "male" | Gender.MALE):
            print(f"{name} is a man and {age} years old")
        case (name, age, "female" | Gender.FEMALE):
            print(f"{name} is a woman and {age} years old")
        case (name, _, gender) if gender is not None:
            print(f"no age specified: {name} is {gender}")
        case (name, age, _) if age is not None:
            print(f"no gender specified: {name} is {age} years old.")

Here the already mentioned pattern matching takes place. In case, it is checked whether there is a match with the pattern, but additionally the specified variables are assigned corresponding values. Details can be found in PEP 622 at www.python.org/dev/peps/pep-0622/. Again, _ serves as a wildcard operator and matches with everything.

Let’s call this classification once as follows:
classify(("Micha", 50, "male"))
classify(("Lili", 42, Gender.FEMALE))
classify(("NO GENDER", 42, None))
classify(("NO AGE", None, "ALL"))
This results in the following outputs:
Micha is a man and 50 years old
Lili is a woman and 42 years old
no gender specified: NO GENDER is 42 years old.
no age specified: NO AGE is ALL

D.3 Miscellaneous

D.3.1 Improvements in Context Managers

Context managers are helpful for resource management when opening or closing files. But they are also useful for managing database connections and many other resources.

Improvement with Python 3.10

With Python 3.10, their syntax becomes a tiny bit more pleasant when using multiple context managers within one with statement:
with (
    open("input1.txt") as input_file1,
    open("input2.txt") as input_file2,
):

D.3.2 Performance Improvements

Python has been improved internally concerning performance in several places. This mainly applies for constructors like str(), bytes(), and bytearray(). They have become faster by about 30 %. Please consult https://bugs.python.org/issue41334 for details.

D.3.3 Extension at zip()

Python 3.9.x

Python provides a built-in function called zip() that allows you to combine two (or more precisely, multiple) iterables into a single unit. This may be used to combine, for example, two lists, one of programming languages and another of version numbers:
>>> languages = ['Java', 'Python']
>>> versions = [17.0, 3.10]
>>>
>>> print(list(zip(languages, versions)))
[('Java', 17.0), ('Python', 3.10)]
If one dataset contains more elements than the other, the merge will be aborted as soon as all elements of the shorter dataset have been processed:
>>> number_list = [1, 2, 3, 4, 5, 6]
>>> str_list = ['one', 'two', 'three']
>>>
>>> print(list(zip(number_list, str_list)))
[(1, 'one'), (2, 'two'), (3, 'three')]

This is often really a very good default setting to be able to work fault-tolerantly. However, sometimes you want to merge the two datasets only if both can provide the same amount of elements. With Python 3.9.x this was only achievable by the help of additional programming efforts.

Improvement with Python 3.10

Since Python 3.10, zip() supports the parameter strict. Use the value True to specify that an exception should be thrown if one of the iterables is exhausted before the others:
>>> number_list = [1, 2, 3, 4, 5, 6]
>>> str_list = ['one', 'two', 'three']
>>>
>>> print(list(zip(number_list, str_list, strict=True)))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: zip() argument 2 is shorter than argument 1

D.3.4 Typechecking Improvements

I have not shown type checks in this book so far, as this is a rather advanced feature of Python. Furthermore, these specifications are optional and only help while coding but are not evaluated at runtime. For clarification, let’s assume the following function initially:
def identity(value):
    return value

Python 3.9.x

To specify for a function that it expects parameters of either type int or float as input and also returns them, you can add the following specifications:
def identity(value: Union[int, float]) -> Union[int, float]:
    return value

Improvement with Python 3.10

The union of types just shown does get a bit clumsy by explicitly specifying Union. With Python 3.10, the notation looks quite natural and is also shorter and more readable:
def identity(value: int | float)  -> int | float:
    return value

This is described as PEP 604 at www.python.org/dev/peps/pep-0604/.

Hint: Interesting Video About What’s New in Python 3.10

To see the new features live in action, I recommend an instructive video available on YouTube at www.youtube.com/watch?v=5-A435hIYio).

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset