Взгляд на новые функции Python 3.11
По данным Python Software Foundation (PSF), Python 3.11 находится в 7-й альфа-версии, выпуск которой запланирован на октябрь 2022 года.
Какие изменения включены в следующую версию?
Пролог
Чтобы оценить различия между версиями 3.10 и 3.11, я установил 2 контейнера докеров.
Первый контейнер для версии 3.10:
docker run -t -d python:3.10.4-bullseye
Второй контейнер для версии 3.11:
docker run -t -d python:3.11-rc-bullseye
Имея два запущенных контейнера, я могу использовать удаленный контейнер против кода для подключения к работающим контейнерам.
Затем я могу выполнить свой код Python в двух средах и увидеть разницу.
В следующих разделах я сначала покажу пример кода, а затем покажу разницу между двумя версиями.
1: Местоположение ошибки
Вывод в версии 3.10:
1
100
Traceback (most recent call last):
File "/usr/local/lib/python3.10/runpy.py", line 196, in _run_module_as_main
return _run_code(code, main_globals, None,
File "/usr/local/lib/python3.10/runpy.py", line 86, in _run_code
exec(code, run_globals)
File "/root/py310/myapp/__main__.py", line 4, in <module>
print(d["key_11"])
KeyError: 'key_11'
Вывод в версии 3.11
1
100
Traceback (most recent call last):
File "<frozen runpy>", line 198, in _run_module_as_main
File "<frozen runpy>", line 88, in _run_code
File "/root/py311/myapp/__main__.py", line 4, in <module>
print(d["key_11"])
~^^^^^^^^^^
KeyError: 'key_11'
Python 3.11 раскрывает разработчику лучшее местонахождение ошибок, что делает процесс разработки потрясающим.
2: Тип ‘self’ type
Тип self уже был представлен в модуле typing extensions, и теперь он продвигается в стандартную библиотеку типизации.
Приведенный выше код представляет структуру каталога. Каталоги имеют подкаталоги, поэтому определение является рекурсивным.
Вывод в Python 3.10:
Traceback (most recent call last):
File "/usr/local/lib/python3.10/runpy.py", line 196, in _run_module_as_main
return _run_code(code, main_globals, None,
File "/usr/local/lib/python3.10/runpy.py", line 86, in _run_code
exec(code, run_globals)
File "/root/py310/myapp/__main__.py", line 2, in <module>
from typing import List, Tuple, Self
Вывод в Python 3.11:
{'content': (['a.txt', 'b.txt'],
[{'content': (['file1', 'file2'], None), 'name': 'dir1'}]),
'name': 'dir2'}
Примечание. Вы можете аннотировать тип subdir по имени самого класса. Но если имя родительского класса изменится, вам придется соответствующим образом изменить все ссылки на аннотации.
Чтобы этот код работал в 3.11 и 3.10, вы можете выполнить импорт следующим образом:
try:
from typing import Self
except ImportError:
from typing_extensions import Self
3: Примечание об исключении
Класс BaseException теперь имеет атрибут класса __note__, по умолчанию равный None.
Вы можете переопределить его любой строкой по вашему выбору и предоставить дополнительную информацию.
Вывод в Python 3.10:
Traceback (most recent call last):
File "/usr/local/lib/python3.10/runpy.py", line 196, in _run_module_as_main
return _run_code(code, main_globals, None,
File "/usr/local/lib/python3.10/runpy.py", line 86, in _run_code
exec(code, run_globals)
File "/root/py310/myapp/__main__.py", line 6, in <module>
raise MyException("some exception")
__main__.MyException: some exception
Вывод в Python 3.11:
Traceback (most recent call last):
File "<frozen runpy>", line 198, in _run_module_as_main
File "<frozen runpy>", line 88, in _run_code
File "/root/py311/myapp/__main__.py", line 6, in <module>
raise MyException("some exception")
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
MyException: some exception
this is my note :)
Мы видим, что примечание было добавлено в вывод, и это позволяет разработчикам быть более коммуникативными в своих исключениях.
4: Группы исключений
В версии 3.11 представлено новое имя типа исключения ExceptionGroup для создания набора исключений и их обработки в предложении except.
В дополнение к этому вводится новый синтаксис except*.
Вывод в Python 3.10:
File "/usr/local/lib/python3.10/runpy.py", line 189, in _run_module_as_main
mod_name, mod_spec, code = _get_main_module_details(_Error)
File "/usr/local/lib/python3.10/runpy.py", line 223, in _get_main_module_details
return _get_module_details(main_name)
File "/usr/local/lib/python3.10/runpy.py", line 157, in _get_module_details
code = loader.get_code(mod_name)
File "<frozen importlib._bootstrap_external>", line 1017, in get_code
File "<frozen importlib._bootstrap_external>", line 947, in source_to_code
File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
File "/root/py310/myapp/__main__.py", line 18
except * (ToYoungException, EmailIsInvalidException) as exception_group_1:
Вывод в Python 3.11:
validations failed
+ Exception Group Traceback (most recent call last):
| File "<frozen runpy>", line 198, in _run_module_as_main
| File "<frozen runpy>", line 88, in _run_code
| ExceptionGroup: (1 sub-exception)
+-+---------------- 1 ----------------
| Exception Group Traceback (most recent call last):
| File "/root/py311/myapp/__main__.py", line 14, in <module>
| raise ExceptionGroup(
| ^^^^^^^^^^^^^^^^^^^^^
| ExceptionGroup: Data validations (2 sub-exceptions)
+-+---------------- 1 ----------------
| ToYoungException: Age must be over 18 - age is 11
+---------------- 2 ----------------
| EmailIsInvalidException: Email must be valid some_wannabe_email
+------------------------------------
|
| The above exception was the direct cause of the following exception:
|
| Traceback (most recent call last):
| File "/root/py311/myapp/__main__.py", line 20, in <module>
| raise ValueError from exception_group_1
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ValueError
+------------------------------------
Как мы видим, это очень ценно, когда у нас есть несколько причин отказа, которые мы хотим раскрыть за один раз.
5. Вложенные асинхронные понимания
Вывод в Python 3.10:
Traceback (most recent call last):
File "/usr/local/lib/python3.10/runpy.py", line 189, in _run_module_as_main
mod_name, mod_spec, code = _get_main_module_details(_Error)
File "/usr/local/lib/python3.10/runpy.py", line 223, in _get_main_module_details
return _get_module_details(main_name)
File "/usr/local/lib/python3.10/runpy.py", line 157, in _get_module_details
code = loader.get_code(mod_name)
File "<frozen importlib._bootstrap_external>", line 1017, in get_code
File "<frozen importlib._bootstrap_external>", line 947, in source_to_code
File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
File "/root/py310/myapp/__main__.py", line 11
return { n: [x async for x in elements(n)] for n in range(3)}
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
SyntaxError: asynchronous comprehension outside of an asynchronous function
Вывод в Python 3.11:
{0: [1], 1: [1, 1], 2: [1, 2, 4], 3: [1, 3, 9, 27], 4: [1, 4, 16, 64, 256]}
В тот момент, когда код входит в блок обработки, он теперь знает об обработке в отношении своего текущего «контекста функции».
Если обработка не является асинхронной, то внутренний блок кода не может иметь асинхронных операторов.
Однако в Python 3.11 включения становятся неявно асинхронными, если они содержат внутренние операторы async , допускающие внутренние включения async.
6: парсер TOML
Синтаксический анализ TOML теперь является частью стандартной библиотеки, как JSON и CSV.
Вывод в Python 3.10:
Traceback (most recent call last):
File "/usr/local/lib/python3.10/runpy.py", line 196, in _run_module_as_main
return _run_code(code, main_globals, None,
File "/usr/local/lib/python3.10/runpy.py", line 86, in _run_code
exec(code, run_globals)
File "/root/py310/myapp/__main__.py", line 2, in <module>
import tomllib
ModuleNotFoundError: No module named 'tomllib'
Вывод в Python 3.11:
{'clients': {'data': [['gamma', 'delta'], [1, 2]], 'hosts': ['alpha', 'omega']},
'database': {'connection_max': 5000,
'enabled': True,
'ports': [8000, 8001, 8002],
'server': '192.168.1.1'},
'owner': {'dob': datetime.datetime(1979, 5, 27, 7, 32, tzinfo=datetime.timezone(datetime.timedelta(days=-1, seconds=57600))),
'name': 'Tom Preston-Werner'},
'servers': {'alpha': {'dc': 'eqdc10', 'ip': '10.0.0.1'},
'beta': {'dc': 'eqdc10', 'ip': '10.0.0.2'}},
'title': 'TOML Example'}
7. Оптимизация производительности
Утверждается, что Python 3.11 на 10–60% быстрее во время выполнения по сравнению с Python 3.10. Подробнее об этом можно прочитать в разделе бенчмаркинга здесь.
Python 3.11 поставляется с набором улучшений, как в производительности, так и в удобстве для разработчиков.
Узнайте об этих обновлениях и улучшите свои навыки программирования!