10 классных функций Python 3. 9

10 классных функций Python 3. 9

Как и большинство поклонников Python, я очень рад изучать и использовать новейшие функции. В этой статье будет представлен обзор возможностей Python 3.9, которые необходимо знать.

Я ознакомился с примечаниями к выпуску, посмотрел обсуждения и составил исчерпывающий гайд о том, что из себя представляют эти функции и как они работают.

Было добавлено несколько новых функций, включая объединение и обновление словарей, строковые методы и внедрение модуля zoneinfo. Также нам представили стабильный и высокопроизводительный парсер.

Давайте разбираться с нововведениями.

1. Операторы обновления и слияния словарей

Во встроенный класс dict добавлено два оператора: | и |= .

| используется для объединения словарей, |= – для их обновления.

В случае конфликта ключей верным будет считаться крайнее правое значение. Это соответствует поведению аналогичных операций dict .

Более детально

Как мы видим, добавлены новые операторы | и |= .

| можно рассматривать как оператор + (сложения) в списках, а |= – как оператор += (расширения).

В Python 3.8 есть несколько способов слияния и обновления словарей.

К примеру, можно использовать first_dict.update(second_dict) . Проблема этого метода в том, что он изменит first_dict на месте. Чтобы этого избежать, нужно объявить временную переменную, сохранить в ней first_dict , а затем выполнить операцию обновления. Но появляется лишняя строка кода, просто чтобы оператор объединения/обновления работал.

Также мы можем применить <**first_dict, **second_dict>. Сложность этого метода в том, что его трудно обнаружить и сложнее понять смысл кода. Кроме того, исключаются типы mapping и учитывается только тип dict. Например, если first_dict – это defaultdict , а second_dict – это тип dict , то программа завершится ошибкой.

Этот способ не работает с подклассами dict , которые содержат функцию _init_ .

Наконец, библиотека collections содержит функцию ChainMap . Она может принять два словаря, как ChainMap(first_dict, second_dict) , и вернуть объединенный словарь, но об этой библиотеке знают немногие.

Для получения более подробной информации вы можете ознакомиться с источником.

2. Новый высокопроизводительный парсер на основе PEG

С Python 3.9 можно отказаться от использования LL (1) в пользу более гибкого и стабильного синтаксического анализатора на основе PEG.

Более детально

Текущий парсер CPython основан на LL (1). Грамматика основана на LL (1), что позволяет парсить ее с помощью LL (1) анализатора. Парсер LL (1) работает сверху вниз и анализирует входные данные слева направо. Грамматика является контекстно-свободной, поэтому контекст токенов не учитывается.

Python 3.9 предлагает заменить его новым парсером на основе PEG, который снимет ограничения Python грамматики LL (1). Будет удален ряд хаков, существующих в текущем синтаксическом анализаторе. В долгосрочной перспективе это снизит стоимость обслуживания.

Несмотря на то, что синтаксические анализаторы и грамматики LL (1) просты в реализации, ограничения не позволяют им выражать общие конструкции естественным образом для разработчика языка и читателя. Парсер смотрит только на один токен вперед, чтобы различать возможности.

Оператор выбора | упорядоченный. Рассмотрим следующее правило:

Контекстно-свободный парсер грамматики LL (1) будет генерировать конструкции, которые при заданной входной строке определят, нужно ли расширять A, B или C. Анализатор PEG отличается. Он проверит, успешна ли первая переменная, и только в случае провала перейдет ко второй или третьей.

Парсер PEG генерирует ровно одно допустимое дерево для строки. Он определенный, в отличие парсер LL (1).

Синтаксический анализатор PEG также напрямую генерирует узлы AST для правила через грамматические действия. За счет этого удается избежать создания промежуточных шагов.

Парсер PEG был тщательно протестирован. У него отлажена производительность. Поэтому для большинства инструкций он расходует примерно 10% от объема памяти и вычислительных ресурсов текущего анализатора. Все благодаря тому, что не создается промежуточное синтаксическое дерево.

Я опустил некоторые детали, чтобы не усложнять прочтение статьи. Для получения более подробной информации вы можете ознакомиться с источником.

3. Новые строковые функции для удаления префикса и суффикса

К объекту str добавлено две новых функции.

1. Первая удаляет префикс – str.removeprefix(‘префикс’) .

2. Вторая удаляет суффикс – str.removesuffix(‘суффикс’) .

Более детально

Одна из обыденных задач в приложении data science, которое включает в себя манипулирование текстом – удалить префикс/суффикс строк. Добавленные к объекту str функции можно использовать для удаления ненужных префиксов и суффиксов из строки.

Как мы уже знаем, первая функция удаляет префикс. Это str.removeprefix(‘префикс’) . Вторая функция удаляет суффикс. Это str.removesuffix(‘суффикс’) .

Строка – это набор символов, и каждый символ имеет индекс в строке. Индексы можно использовать вместе с : , чтобы вернуть подмножество строки. Эта функция известна как slice (срез) строки.

Если мы говорим о функциях, они проверяют, начинается ли строка с префикса (заканчивается ли она суффиксом), и если да, то возвращают строку без префикса или после суффикса, используя функцию среза str[:] .

Поскольку эти функции являются частью стандартной библиотеки, мы получаем согласованный, менее хрупкий, высокопроизводительный и более наглядный API.

Для получения более подробной информации вы можете ознакомиться с источником.

4. Подсказки типов для встроенных универсальных типов

Аннотирование программ стало проще за счет удаления иерархии параллельных типов в Python.

Добавлена поддержка универсального синтаксиса во всех стандартных коллекциях, доступных в модуле набора текста.

Мы можем использовать встроенные типы коллекций list или dict в качестве универсальных типов вместо использования typing.List или typing.Dict в сигнатуре нашей функции.

Код стал выглядеть чище, а его понимание и объяснение упростилось.

Более детально

Несмотря на то, что Python – это язык с динамической типизацией, аннотация типов в программе позволяет проводить самоанализ. Впоследствии аннотацию можно использовать для создания API проверки типов во время выполнения.

Как я говорил ранее, в Python 3.9 добавили поддержку универсального синтаксиса во всех стандартных коллекциях, доступных в модуле набора текста.

Универсальный тип – это обычно контейнер, к примеру list . Это тип, который можно параметризовать. Параметризованный тип – это пример универсального дженерика с ожидаемыми типами для элементов контейнера типа list[str] .

Мы можем использовать встроенные типы коллекций list или dict в качестве универсальных типов вместо использования typing.List или typing.Dict .

Например, мы могли бы управлять проверкой типов среды выполнения Python, аннотируя код:

Ряд функций статической типизации был постепенно построен поверх существующей среды выполнения Python. Некоторые из них были ограничены существующим синтаксисом и поведением во время выполнения. Поэтому в модуле типизации возникла дублированная иерархия коллекций из-за дженериков.

Например, мы увидим typing.List , typing.Dictionary вместе со встроенными list , dictionary и т. д. Это позволяет писать код:

Для получения более подробной информации вы можете ознакомиться с источником.

5. Поддержка часового пояса IANA в DateTime

Модуль zoneinfo был создан в качестве поддержки базы данных часовых поясов IANA. Эта поддержка была добавлена в стандартную библиотеку.

Часовые пояса IANA часто называют tz или zone info. Существует много часовых поясов IANA с разными путями поиска для указания часового пояса IANA объекта datetime . Например, мы можем передать имя пути поиска объекту datetime как Continent/City , чтобы установить его tzinfo .

dt = datetime(2000, 01, 25, 01, tzinfo=ZoneInfo(«Europe/London»))

Если мы передадим неверный ключ, возникнет ошибка zoneinfo.ZoneInfoNotFoundError .

Более детально

Библиотека datetime используется для создания объекта datetime и указания его часового пояса, путем установки свойства tzinfo . Все может обернуться созданием сложных правил часового пояса при использовании базового показателя datetime.tzinfo .

В большинстве случаев нужно просто установить объект и его часовой пояс: UTC, локальный часовой пояс системы, или часовой пояс IANA.

Можно создать объект zoneinfo.ZoneInfo(key) , где ключ имеет строковый тип, указывающий путь поиска файла зоны в базе данных часовых поясов системы. Объект zoneinfo.ZoneInfo(key) может быть создан и установлен как свойство tzinfo объекта datetime .

Для получения более подробной информации вы можете ознакомиться с источником.

6. Возможность отмены одновременных фьючерсов.

В concurrent.futures.Executor.shutdown() добавлен новый параметр cancel_futures .

Он отменяет все отложенные фьючерсы, которые не были запущены.

До версии 3.9 процесс ожидал их завершения перед завершением работы исполнителя.

Пояснение

Новый параметр cancel_futures был добавлен в ThreadPoolExecutor и ProcessPoolExecutor . Это работает так: если его значение – True , все ожидающие фьючерсы отменяются при вызове функции shutdown() .

При выполнении shutdown() интерпретатор проверяет, не собран ли исполнитель сборщиком мусора. Если он все еще находится в памяти, он получает все ожидающие обработки элементы, а затем отменяет фьючерсы.

Когда не остается незавершенных рабочих элементов, он завершает работу.

Для получения более подробной информации вы можете ознакомиться с источником.

7. Улучшения AsyncIO и многопроцессорности

В библиотеку asyncio и многопроцессорную обработку были внесен ряд улучшений.

1. Параметр reuse_address asyncio.loop.create_datagram_endpoint() больше не поддерживается из-за серьезных пробелов в безопасности.

2. Добавлены новые сопрограммы: shutdown_default_executor() и asyncio.to_thread(). shutdown_default_executor назначает завершение работы для исполнителя по умолчанию, который ждет завершения ThreadPoolExecutor. asyncio.to_thread() в основном используется для запуска функций, связанных с вводом-выводом, в отдельном потоке, чтобы избежать блокировки цикла событий.

Что касается улучшений библиотеки многопроцессорности, в класс multiprocessing.SimpleQueue был добавлен новый метод close() .

Этот метод точно закрывает очередь. Это гарантирует, что очередь будет закрыта и не останется дольше ожидаемого. Помните, что методы get() , put() , empty() не должны вызываться после закрытия очереди.

Для получения более подробной информации вы можете ознакомиться с источником.

8. Постоянные ошибки импорта пакетов

Основная проблема импортирования библиотек Python заключалась в несогласованном поведении, когда относительный импорт проходил мимо пакета верхнего уровня.

Встроенная функция __import__() вызывает ошибку ValueError , а importlib.__import__() вызывает ошибку ImportError .

Теперь это исправили. __import__() вызывает ImportError вместо ValueError .

Для получения более подробной информации вы можете ознакомиться с источником.

9. Генерация случайных байтов

Еще одна функция, добавленная в версии 3.9 – random.Random.randbytes() . Эта функция может использоваться для генерации случайных байтов.

Можно генерировать случайные числа, но что, если нужно генерировать случайные байты? Раньше разработчикам приходилось для этого проявлять изобретательность. Хотя можно использовать os.getrandom() , os.urandom() или secrets.token_bytes() , но нельзя генерировать псевдослучайные паттерны.

К примеру, чтобы гарантировать, что случайные числа генерируются с ожидаемым поведением и процесс воспроизводится, обычно используется модуль random.Random .

В результате был введен метод random.Random.randbytes() . Он также может генерировать случайные байты контролируемым способом.

Для получения более подробной информации вы можете ознакомиться с источником.

10. Исправление функции замены строки

Раньше «».replace(«», s, n) возвращал пустую строку вместо s для всех ненулевых n .

Этот баг сбивал с толку пользователей и приводил к нестабильному поведению приложений.

В Python 3.9 проблема была устранена, и теперь функция замены совместима с «».replace(«», s) .

Работает она следующим образом: для заданного максимального аргумента вхождения замены, набор символов из строки заменяется новым набором символов:

string.replace(s, old, new[, maxreplace])

В этом случае возвращается копия строки s со всеми вхождениями старой подстроки, замененной на новую. Если указан необязательный аргумент maxreplace, заменяются первые экземпляры maxreplace.

До этого функция replace имела непоследовательное поведение

В Python 3.9 также был исключен ряд избыточных функций, таких как Py_UNICODE_MATCH .

Если вы хотите узнать больше об этих улучшениях, прочтите официальное руководство здесь .

Нововведения в популярном языке программирования можно изучить самостоятельно, но придется потратить много времени и сил на поиск и систематизацию информации. Если ваш опыт в профессии еще не так велик, обратите внимание на факультет Python-разработки GeekBrains. Под руководством опытных преподавателей вы получите необходимые знания, а успешно завершившим обучение студентам онлайн-академия поможет с трудоустройством.