19 мая состоялся релиз Python 3.9.0 beta1. Нововведения, которые включены в данную бету, с высокой вероятностью попадут в итоговый релиз. Небольшие изменения в функционале возможны до выпуска release candidate, который запланирован на 10.08.2020. Но появление новых фич уже не планируется.
Рассмотрим новые возможности и изменения, которые появились в данной версии, и с которыми, наиболее вероятно, столкнется рядовой пользователь Python.
РЕКОМЕНДУЕМ:
Система распознавания лиц на Python
Вводится новый оператор объединения словарей
В предыдущих версиях существует несколько способов объединения словарей. Но каждый из них имеет определенные недостатки или ограничения:
- Метод dict.update.
Данный метод модифицирует словарь, к которому применяется. Например, выражение dict_1.update(dict_2) изменяет словарь dict_1. Это не всегда удобно на практике. - Использование распаковки вида {**d1, **d2}В PEP 584 привели цитату Гвидо, который сказал о том, что «даже если пользователи Python знакомы с использованием конструкции распаковки **d в другом контексте, он сомневается, что они смогут сходу предложить такой способ объединения словарей». Гвидо признается, что и сам забыл про этот способ.К тому же, конструкция {**d1, **d2} игнорирует mapping-типы. Поэтому не все подклассы dict будут совместимы с ней (например, collections.defaultdict не может быть использован).
- Использование collections.ChainMapДанный класс не очень распространен, и многие считают его неочевидным. Если в объединяемых словарях есть дубликаты, то все они будут храниться в ChainMap. А при изменении значения по ключу, будет изменяться только первый найденный элемент. Кроме того, как и в случае с распаковкой, есть проблемы совместимости с подклассами dict.
12345678910>>> from collections import ChainMap>>> dict_1 = { 'key_1': 1, 'key_2': 2 }>>> dict_2 = { 'key_1': 10, 'key_3': 3 }>>> chain = ChainMap(dict_1, dict_2)>>> chainChainMap({'key_1': 1, 'key_2': 2}, {'key_1': 10, 'key_3': 3})>>> chain['key_1'] = 999 # Изменяется только первый найденный элементChainMap({'key_1': 999, 'key_2': 2}, {'key_1': 10, 'key_3': 3}) - Использование конструкции dict(dict_1, **dict_2)Также не очень распространенный метод. К тому же, в этом случае требуется чтобы dict_2 был только со строковыми ключами.
1234>>> dict_1 = {'key_1': 1}>>> dict_2 = {2: 2}>>> dict(dict_1, **dict_2)TypeError: keywords must be strings
В Python 3.9 добавляется оператор объединения словарей |, работу которого легче всего продемонстрировать на примере:
1 2 3 4 5 6 |
>>> dict_1 = {'key_1': 1, 'key_2': 2} >>> dict_2 = {'key_1': 99, 'key_3': 3} >>> dict_1 | dict_2 {'key_1': 99, 'key_2': 2, 'key_3': 3} >>> dict_2 | dict_1 {'key_2': 2, 'key_1': 1, 'key_3': 3} |
То есть операция объединения не является коммутативной. Если в объединяемых словарях имеются одинаковые ключи, значение берется из последнего операнда. Также поддерживается расширенный оператор присваивания |=.
1 2 3 |
>>> dict_1 |= dict_2 >>> dict_1 {'key_1': 99, 'key_2': 2, 'key_3': 3} |
Новые методы строк для удаления префиксов и суффиксов
Стандартный тип str получил пару новых методов для удаления префикса и суффикса:
1 2 3 4 5 6 7 |
>>> text = 'test_name' >>> text.removeprefix('test_') 'name' >>> text = 'name_test' >>> text.removesuffix('_test') 'name' |
Упрощается аннотирование типов (type hinting)
Авторы говорят о том, что исторически сформировалось, по сути, две дублирующих иерархии типов. При аннотировании была необходимость импорта типов из модуля typing. Такое указание типов становится устаревшим:
1 2 3 |
from typing import Dict, List def func(arg: Dict[str, List[str]]) -> int: pass |
Начиная с версии 3.7 можно было использовать конструкцию from __future__ для отложенной обработки аннотаций, что позволяет использовать типы стандартных коллекций:
1 2 3 |
from __future__ import annotations def func(arg: dict[str, list[str]]) -> int: pass |
И, с приходом версии 3.9, можно будет полностью перейти на аннотирование через стандартные коллекции. Как указано в PEP 585, поддержка устаревшей функциональности будет удалена из модуля typing через 5 лет после выпуска Python 3.9.
Полный список типов, которые можно будет использовать
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
tuple list dict set frozenset type collections.deque collections.defaultdict collections.OrderedDict collections.Counter collections.ChainMap collections.abc.Awaitable collections.abc.Coroutine collections.abc.AsyncIterable collections.abc.AsyncIterator collections.abc.AsyncGenerator collections.abc.Iterable collections.abc.Iterator collections.abc.Generator collections.abc.Reversible collections.abc.Container collections.abc.Collection collections.abc.Callable collections.abc.Set # typing.AbstractSet collections.abc.MutableSet collections.abc.Mapping collections.abc.MutableMapping collections.abc.Sequence collections.abc.MutableSequence collections.abc.ByteString collections.abc.MappingView collections.abc.KeysView collections.abc.ItemsView collections.abc.ValuesView contextlib.AbstractContextManager # вместо typing.ContextManager contextlib.AbstractAsyncContextManager # вместо typing.AsyncContextManager re.Pattern # вместо typing.Pattern, typing.re.Pattern re.Match # вместо typing.Match, typing.re.Match |
РЕКОМЕНДУЕМ:
Что Python 3.9 нам готовит?
Гибкие аннотации функций и переменных
В модуль typing добавляется тип Annotated, с помощью которого можно добавлять существующим типам контекстно-зависимые метаданные. Использование конструкции Annotated[T, x] означает, что тип T аннотируется метаданными x. Например:
1 |
my_type = Annotated[int, ValueRange(-100, 100)] |
Подробное описание данной, достаточно специфичной темы приводится в PEP 593 Flexible function and variable annotations.
А так же…
Кроме описанных выше изменений, в версии 3.9 исправлены ряд багов и упоминается об ускорении работы встроенных типов range, tuple, set, frozenset, list, dict.
В рамках PEP 617 анонсирован новый PEG-парсер грамматики для CPython. Он приходит на смену LL(1)-парсера и расширяет возможности языка, поддерживая более сложные и гибкие грамматические конструкции выражений.
Также в PEP 602 объявлено, что начиная с версии 3.9, выпуск новых версий будет осуществляться раз в год, а цикл разработки каждой новой версии (3.10, 3.11 и т.д.) будет занимать 17 месяцев. Стабильность — залог успеха!