Python 3.9 или нам необходима версия 4.0?
В современном быстро меняющемся технологическом ландшафте быть в курсе новейших языков программирования и их обновлений крайне важно. Python, универсальный язык программирования высокого уровня, является фаворитом среди разработчиков. Python 3.9, последняя версия на момент моего последнего обновления в сентябре 2021 года, предлагает множество усовершенствований. Однако возможность появления версии Python 4.0 вызывает интригующие споры.
500 показов
1.1K открытий
Python 3.9 появился на рынке в октябре 2020 года, принеся с собой набор улучшений по сравнению с предыдущими версиями. Эта итерация принесла улучшения, которые повысили читабельность и снизили сложность кодирования.
Например, в Python 3.9 появились операторы объединения для словарей:
Переход от Python 2 к Python 3 был значительным и включал в себя многочисленные изменения, несовместимые с обратной стороной. Однако разработчики заявили, что переход на Python 4.0, когда он произойдет, не будет таким разрушительным. Несмотря на это заверение, сообщество программистов заинтриговано тем, что может повлечь за собой Python 4.0.
Будет ли в Python 4.0 более оптимизированная производительность? Или же в нем появится более мощная система подсказок типов для облегчения понимания кода? Пока что Python 4.0 остается диковинкой в мире программирования.
Учитывая приверженность Python к обратной совместимости, обновление с Python 3.9 до Python 4.0 вряд ли вызовет значительные трудности при миграции. Тем не менее, стоит ли вам переходить на Python 4.0 после его выхода, зависит от ваших конкретных потребностей и от того, какие новые возможности предоставляет Python 4.0.
Независимо от того, выберете ли вы Python 3.9 или решите перейти на Python 4.0, когда он выйдет, изучение Python остается бесценной инвестицией. Многочисленные онлайн-платформы предлагают комплексные курсы, рассчитанные на разные уровни обучения.
Возьмем, к примеру, компанию Skypro. Известная своим широким спектром курсов по языкам программирования, включая Python, Skypro помогает учащимся ориентироваться в тонкостях Python и его различных приложениях. Эти курсы посвящены основам Python и таким продвинутым темам, как анализ данных, машинное обучение и веб-разработка.
Python 3.9, благодаря своей читабельности и простоте использования, является чрезвычайно полезным инструментом для разработчиков. Однако, поскольку мы с нетерпением ожидаем выхода Python 4.0 и потенциальных возможностей, которые он может принести, один факт остается очевидным: способность адаптироваться и изучать новые языки программирования и их обновления критически важны в нашем мире, управляемом цифровыми технологиями.
Вышла новая версия Python: что изменилось?

Python 3.11.0 вышла в релиз — как утверждают создатели, она более стабильная, быстрая и с множеством новых функций и оптимизаций.
Курс Микросервисная архитектура.
програма, яка допоможе опанувати головні принципи розробки мікросервісної архітектури, щоби ви могли проєктувати незалежні сервіси, а потім інтегрувати їх в одну систему. Практики буде багато.
Что нового
Есть ряд важных общих изменений языка:
-
в новой версии включены подробные местоположения ошибок в трассировках — теперь некоторые сообщения об ошибках Python станут более понятными;
Курс Микросервисная архитектура.
програма, яка допоможе опанувати головні принципи розробки мікросервісної архітектури, щоби ви могли проєктувати незалежні сервіси, а потім інтегрувати їх в одну систему. Практики буде багато.

Кроме того, в выпуске есть множество других заслуживающих внимания новинок, например, PEP 673 (самостоятельный тип) и PEP 675 (произвольный тип литеральной строки).
Еще исправлен ряд ошибок и сбоев в ядре и встроенных модулях. В библиотеке ускорена работа семаформа и исправлен флаг для использования границы CONFORM. Ранее разработчики объявили устаревшим asyncio.Task.cancel(“message”) и планировали выкинуть его из библиотеки, но все же решили оставить.
Также есть несколько важных изменений в сфере безопасности: исправлено умножение списка на целое число, а в Linux многопроцессорный модуль возвращается к использованию сокетов домена unix, поддерживаемых файловой системой, для связи с процессом forkserver (вместо пространства имен абстрактных сокетов Linux). Затрагивается только код, который использует метод запуска «forkserver».
Курс Управління командою в бізнесі.
Онлайн-курс для ефективного управління командою, спрямований на створення проактивних та самостійних команд, де мікроменеджмент не потрібний.
Краткая история Python

Python был разработан около тридцати лет назад, первая его официальная версия вышла в 1991 году и имела номер 0.9. После этого довольно долгое время язык развивался, и популярность он получил в 2000-х годах, во время мажорной второй версии. Однако уже тогда было понятно, что в языке необходимы изменения, которые будут обратно несовместимы с текущими версиями, такие как например, изменения в поведении юникодных строк. Однако вторая версия Python была уже очень популярна к этому моменту, поэтому третья работа над третьей версией велась одновременно с работой над 2.7. Довольно долго у core-разработчиков Python не было определенной стратегии, поэтому до версии 3.4 изменения были довольно хаотичны.

С 2019 года Python адаптирует годичные релизные циклы. Это изменение было представлено в PEP-602 Что это значит для пользоватеоей Python?

- новая минорная (3.X.0) версия выходит каждый год
- фаза активной разработки версии 3.X+1.0 начинается в тот момент, когда в релих отправляется 3.X.beta и продолжается 12 месяцев
- каждая минорная версия активно поддерживается в течении полутора лет
- каждая минорная версия получает обновления безопасности в течении трех с половиной лет Пример расписания релизов для версии 3.9 можно посмотреть на рисунке:
What’s new in Python 3.9?
Релиз Python 3.9 произошел 2020-10-05. Рассмотрим что есть нового в этой версии.
Работа со словарями
Допустим, есть два словаря, которые мы зотим объединить.
В версиях до 3.9 можно было бы сделать таким образом:
pycon = europython =
Синтаксис ** разворачивает словарь, и когда они объединяются, более позднее значение затирается более новым. Аналогичные дейтсвия можно совершить, если использовать следующий синтаксис:
merged_dict = pycon.copy() for key, value in europython.items(): merged_dict[key] = value merged_dict
Или таким образом:
pycon.update(europython) pycon
Этот способ пойдойдет в случае если нужно изменить первоначальный словарь.
merged_dict = pycon.copy().update(europython)
Однако если нужно сохранить эти данные в новом словаре, этим способом воспользоваться нельзя, в последнем примере
merged_dict is None
True
В библиотеке collections есть объект ChainMap, который тоже обхединяет словари, но его результатом будет объект ChainMap, а не словарь. Он состоит из нескольких словарей, следующих друг за другом. Если взять значение по ключу, то вернется то значение, которое встречается раньше. То есть, в этом примере для ключа 2019, вернется значение Cleveland
from collections import ChainMap merged_dict = ChainMap(pycon, europython) merged_dict
ChainMap(, )
В Python 3.8 был представлен walrus-оператор. С его помощью можно решить проблему примера с update и скопировать словарь в новую переменную:In [11]:
(merged_dict := pycon.copy()).update(europython) merged_dict
В Python 3.9 в PEP-0614 добавлен синтаксис | (читается как pipe), который объединяет словари аналогично первому примеру:
pycon | europython
При этом первоначальный словарь не меняется:
pycon
Если все-таки нужно обновить первоначальный словарь, можно воспользоваться синтаксисом |= (работает по аналогии с +=): a |= b a = a|bIn [16]:
pycon |= europython pycon
Важно помнить, что поскольку более поздние значения перезаписывают более ранние значения, эта операция может быть не коммуникативна.
print(europython | pycon) print(pycon | europython)
Синтаксис | работает только непосредственно со словарями, тогда как синтаксис ** работает и с orderedict и с другими подобными словарям объектами.
Изменения в работе с декораторами
До версии 3.9 в качестве декораторов могли выступать функции или классы, но не такие объекты как списки или словари. Рассмотрим пример, в котором это будет удобно использовать. Допустим есть UI-приложение с кнопками, и нужно добавить какое-то сообщение по нажатию на каждую кнопку. Было бы удобно это сделать с помощью декоратора, но что делать, если для каждой кнопки нужно печатать различные сообщения. Это можно сделать следующим образом:In [ ]:
buttons = [QPushButton(f'Button i>') for i in range(10)] button_0 = buttons[0] button_1 = buttons[1] @button_0.clicked.connect def say_hello(): message.setText("Hello, World!") @button_1.clicked.connect def say_goodbye(): message.setText("Goodbye, World!")
Создаем list comprehension из функций, явно присваем объектам значения элементов списка, и их можно использовать в качестве декораторов. Это будет работать, однако не будет эффективно, если объектов из которых будут созданы декораторы, будет достаточно много.
Это не единственный способ, но другие будут довольно неоднозначными. Рассмотрим два из них. В первом случае создадим функцию, которая будет возвращать необходимую для декоратора функцию:In [ ]:
def _(x): return x @_(buttons[0].clicked.connect) def say_hello(): .
Использование eval :In [ ]:
@eval("buttons[1].clicked.connect") def say_bye(): .
В Python 3.9 стало возможно создавать декораторы из любых объектов, например из элементов списков и словарей. Можно рассмотреть синтаксис, который реализует тот же самый пример:
@buttons[0].clicked.connect def say_hello(): message.setText("Hello, World!") @buttons[1].clicked.connect def say_goodbye(): message.setText("Goodbye, World!")
Похожим образом будет выглядеть синтаксис для значений словаря:
buttons = @buttons['hello'].clicked.connect def say_hello(): message.setText("Hello, World!") @buttons['goodbye'].clicked.connect def say_goodbye(): message.setText("Goodbye, World!")
Этот функционал, несмотря на то, что не приносит новых возможностей, позволяет писать более чистый код и избегать рискованных решений вроде использования eval .
Изменения в синтаксисе типирования
Дженерики
Дженерики это типы, которые могут быть параметризованы, обычно являются контейнерами, например dict. Параметризованные дженерики это типы, для которых указан внутренний тип, например dict[str, int]
Начиная с Python 3.7 стало можно указывать тип объекта, конкретизируя тип внутренних элементов контейнеры. Но для этого нужно было импортировать таки типы как List из модуля typing :
from typing import List, Dict def find(haystack: Dict[str, List[int]]) -> int: #def find(haystack: dict) -> int: .
Можно было не конкретизировать тип внутренних значений, для этого не нужно было импортировать дополинтельные типы и можно было использовать стандартные типы dict и list. Благодаря этому нововведению, внешние библиотеки такие как Mypy стали распознавать дженерики.
Также, в версии 3.9 стало можно пользоваться аннотациями без явного их импорта из модуля __future__
Расширение возможностей аннотаций
Аннотации были доступны для использования и в более ранних версиях Python, однако их функция была скорее информационной, использовались они в первую очередь для документации. Синтаксис использования аннотаций до Python 3.9 выглядел таким образом:
def speed(distance: "feet", time: "seconds") -> "miles per hour": fps2mph = 3600 / 5280 return distance / time * fps2mph
В Python 3.9 появился новый объект типа Annotated, который принимает на вход два аргумента, первый это реальный тип, которым должен обладать аннотриуемый объект, а второй это название для целей документации:
from typing import Annotated def speed( distance: Annotated[float, "feet"], time: Annotated[float, "seconds"]) -> Annotated[float, "miles per hour"]: fps2mph = 3600 / 5280 return distance / time * fps2mph
Когда происходит проверка аннотаций, проверяется только первый аргумент, в котором находится «реальный» тип объекта, а второй использовуется как и в предыдущих версиях:
speed.__annotations__
Изменения связанные с часовыми поясами
В предыдущих версиях Python, модуль datetime не содержал информации о часовых поясах, и рекомендованным способом работы с ними была библиотека python-dateutil .
Однако начиная с Python 3.9 появился модуль zoneinfo, который содержит информацию о часовых поясах и позволяет создавать объекты им соответствующие:
from datetime import datetime, timezone from zoneinfo import ZoneInfo local_tz = ZoneInfo('Europe/Amsterdam') datetime.now(tz=timezone.utc), datetime.now()
(datetime.datetime(2021, 5, 4, 15, 58, 36, 295472, tzinfo=datetime.timezone.utc), datetime.datetime(2021, 5, 4, 17, 58, 36, 295477))
В стандартной библиотеке не было информации ни о каких часовых поясах, кроме utc, и необходимо было использовать pytz чтобы создать объект, содержащий информацию о часовом поясе. Теперь это можно сделать без установки дополнительных библиотек:In [32]:
from zoneinfo import ZoneInfo local_tz = ZoneInfo('Europe/Amsterdam') datetime.now(tz=local_tz)
(datetime.datetime(2021, 5, 4, 17, 58, 37, 765947, tzinfo=zoneinfo.ZoneInfo(key='Europe/Amsterdam')),)
Всего часовых поясов больше чем можно было бы предположить, и многие из них представлены в модуле `zoneinfo`
import zoneinfo tzs = zoneinfo.available_timezones() len(tzs)
Новые методы работы со строкам
Иногда нужно убрать первые или последние несколько символов из строки. Есть метод strip , который обладает казалось бы похожим функционалом, но он может иногда давать неожиданные результаты Например в таком случае:
"ababbbbbbaaccc".lstrip("ab")
В Python 3.9 были добавлены функции removeprefix , removesuffix , которые выполняют то, что от них ожидается: удаляют первые или последние несколько символов строки.In [35]:
"ababbbbbbaaccc".removeprefix("ab")
'abbbbbbaaccc'
"ababbbbbbaaccc".removesuffix("c")
'ababbbbbbaacc'
Если строка не содержит суффикс или префикс, строка не меняется, никаких исключений не появляется.
"ababbbbbbaaccc".removesuffix("something else")
'ababbbbbbaaccc'
Python 3.10
Последняя версия Python 3.10 это 0b3 , которая вышла 17 июня 2021 года. Согласно расписанию релизов, полноценный релиз появится примерно в октябре 2021. Пока официального релиза нет, версия не доступна в пакетных менеджерах (таких как brew). Соответственно, чтобы ее установить, билд нужно скачать вручную с www.python.org и уствноваить на своей машине. Рассмотрим изменения, доступные в этой Python 3.9.
Pattern Matching
В более ранних версиях Python если нужно описать различное поведение, в зависимости от того, какой объект используется, скорее всего будет использоваться условный оператор:In [ ]:
if isinstance(x, tuple) and len(x) == 2: host, port = x mode = "http" elif isinstance(x, tuple) and len(x) == 3: host, port, mode = x
Однако в Python 3.10 вместе с PEP-0635 будет добавлен новый оператор match, который может использоваться с case:In [ ]:
match x: case host, port: mode = "http" case host, port, mode: pass cass Class1: . case host == 'localhost' .
Также с его помощью будет удобно реализовывать, например, обработку ошибок:In [ ]:
def http_error(status): match status: case 400: return "Bad request" case 404: return "Not found" case 418: return "I'm a teapot" case _: return "Something's wrong with the Internet"
Это одно из самых «громких» нововведений в последних версиях Python и возможно самое ожидаемое коммьюнити.
Более удобное использование Union для типирования:
Если раньше чтобы указать, что аргумент функции может быть одним из нескольких типов, необходимо было использовать Union, импортируемый из пакета typing:In [ ]:
from typing import Union def square(number: Union[int, float]) -> Union[int, float]: return number ** 2
То начиная с Python 3.10 можно будет заменить его оператором pipe | и, соответственно, избавиться от импорта:In [ ]:
def square(number: int | float) -> int | float: return number ** 2
Контекстные менеджеры
Синтаксис работы с контекстными менеджерами упростится, теперь несколько контекстных менеджеров можно объединять в одном with , а так же не обязательно присваивать им локальные имена:In [ ]:
with ( CtxManager1(), CtxManager2() ): . with (CtxManager1() as example, CtxManager2()): . with ( CtxManager1() as example1, CtxManager2() as example2 ): .
Более информативные сообщения об ошибках
Наверняка многие из читателей сталкивались с тем, что сообщение об ошибке слишком общее и само по себе не говорит о том, что нужно сделать чтобы ошибку исправить. В новой версиеи Python core-разработчики улучшили самые распространенные из них и теперь сообщения об ошибках будут намного более читабельными:In [ ]:
expected = SyntaxError: '>>> if rocket.position > event_horizon File "", line 1 if rocket.position > event_horizon ^ SyntaxError: expected ':'>>> for x,y in range(100)> File "", line 1 for x,y in range(100)> ^ SyntaxError: did you forget parentheses around the comprehension target?if rocket.position = event_horizon: File "", line 1 if rocket.position = event_horizon: ^ SyntaxError: cannot assign to attribute here. Maybe you meant '==' insteaddef foo(): . if lel: . x = 2 File "", line 3 x = 2 ^ IndentationError: expected an indented block after 'if' statement in line 2Остальное
- Модуль distutils постепенно выыводится из употребления, чтобы быть полностью удаленным в Python 3.12. Это связано с тем, что его функции были полностью заменены такими модулями как setuptools и packaging.
- Улучшение читабельности сообщений в модуле debugging
Это не все изменения которые попадут в Python 3.10, с полным списком можно ознакомиться посмотрев список изменений .
Прокачать Python можно на курсах:
- Python Developer. Basic
- Python Developer. Professional
- Web-разработчик на Python
Python-update
Если версия Python, установленная на вашей ОС, не поддерживается модулями или поллером, то необходимо установить дополнительно новую версию Python, удовлетворяющую всем требованиям.
Важно: Изменять системную версию Python на новую - не рекомендуется! Единственный правильный способ - это установить новую версию параллельно системной. Иначе могут перестать работать различные системные службы и утилиты, использующие Python.
Сначала убедитесь, что у вас установлены все необходимые глобальные пакеты в Python, которые необходимы глобально для запуска виртуального окружения, для сборки других зависимостей.
sudo apt install -y python3-dev python3-pip python3-venv libffi-dev
После того, как все установлено, зайдите на сайт https://www.python.org/downloads/source/ и скопируйте номер последней версии текущей ветки или предыдущей, если текущая ветка слишком свежая. Например, если последняя версия 3.11.1, то надежней все таки установить версию 3.10.11, т.к. сразу после выхода новой версии (3.11) есть вероятность того, что не все зависимые пакеты ее поддерживают.
Далее вам нужно создать временную переменную окружения, значение которой будет содержать номер версии Python, которую вы собираетесь установить.
PY_VER=3.11.5
Далее приведены команды, которые вы просто выполняете по одной, одну за другой, чтобы контролировать процесс и в случае ошибки не выполнять остальные команды. Копируйте по одной строке и выполняйте:
curl -o python.tgz "/Python-$.tgz">https://www.python.org/ftp/python/$/Python-$.tgz" tar xzf python.tgz cd Python-$ ./configure --enable-optimizations make -j $(nproc) sudo -H make altinstall curl -sS https://bootstrap.pypa.io/get-pip.py | sudo -H python3.11 pip3.11 --version cd .. sudo rm -rf Python-$ python.tgz
После выполнения всех этих действий у вас в системе будет установлена еще одна версия Python. В данном случае это Python 3.11 а также инструмент pip тоже с версией 3.11.
Чтобы использовать именно эту версию python и pip, вам нужно указывать целиком имена файлов, которые вы запускаете. Например:
python3.11 --version pip3.11 --version
Теперь, чтобы создать виртуальное окружение для какого-либо модуля либо поллера, вам нужно использовать следующий синтаксис:
sudo python3.11 -m venv venv sudo venv/bin/pip install -U pip wheel и т.д.