Взгляд на новые функции 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 поставляется с набором улучшений, как в производительности, так и в удобстве для разработчиков.
Узнайте об этих обновлениях и улучшите свои навыки программирования!