Коробка с питоном
Там у Python 3.11 сегодня релиз, пройдемся по изменениям. Разделю пост на 2 части, сначала расскажу про всё остальное, а потом про typing, который снова прокачали. 1) Теперь Питон быстрее на 10-60% чем предыдущая версия. Почему такой разброс и где что ускорилось…
Немного с запозданием, но поговорим про новые фичи в typing.
1)
Есть такой специальный класс как
Теперь для описания полей в нём добавили три вещи:
1.
2.
3. Аргумент
Почитать подробнее о нём можно вот тут
2) Self.
Ликуйте, господа, мы дождались! Больше никаких костылей с TypeVar!
Аннотация
3) LiteralString.
Относительно этого тайпхинта строки бывают двух типов - литеральные строки и произвольные строки. К литеральным строкам относятся константы, к произвольным - всё остальное. Данный тип указывает, что строка должна быть первого типа, на остальное оно будет ругаться. Вот пример:
4) Data class transforms
Декоратор который декорирует класс, метакласс или функцию которые являются декоратором. Получившийся декоратор умеет показывать тайпчекеру что декорируемый объект имеет фичи как у датакласса. Причина создания такой штуки проста - нет стандартного пути обозначения, что какой-то объект имеет свойства, присущие датаклассу. Привет Pydantic! PEP 681 читать здесь.
5) Вариативные дженерики.
Есть такая штука как
Зачем это нужно: мы все знаем, что всякие датасотонисты любят наш питон из-за обилия всяких инструментов по типу NumPy или Pandas. Вариативные дженерики позволяют параметризировать структуры, которые подобны массивам, что в свою очередь позволяет находить ошибки при операции с этими структурами тайпчекеру.
PEP 646 читать здесь.
#pep
1)
NotRequired
и Required поля в TypedDict
.Есть такой специальный класс как
TypedDict
- он позволяет добавить тайпхинты к словарю.Теперь для описания полей в нём добавили три вещи:
1.
NotRequired
- показывает, что данного поля может и не быть в словаре.2.
Required
- показывает, что данное поле обязательно должно быть в словаре3. Аргумент
total
- если его значение ложно, то все поля в этом классе будут отмечены как NotRequired
. По умолчанию оно истинно.Почитать подробнее о нём можно вот тут
2) Self.
Ликуйте, господа, мы дождались! Больше никаких костылей с TypeVar!
Аннотация
Self
показывает что мы хотим вернуть инстанс текущего класса. Выглядит это как-то так:class MyLock:Простенько и лаконично. Вот PEP 673.
def __enter__(self) -> Self:
self.lock()
return self
3) LiteralString.
Относительно этого тайпхинта строки бывают двух типов - литеральные строки и произвольные строки. К литеральным строкам относятся константы, к произвольным - всё остальное. Данный тип указывает, что строка должна быть первого типа, на остальное оно будет ругаться. Вот пример:
def run_query(sql: LiteralString) -> ...Исходя из примера видно, что использоваться это будет во всяких функциях, которые выполняют, например, SQL запросы или CLI-утилитах не давая на уровне тайпчекера засунуть в функцию очередной
...
def caller(
arbitrary_string: str,
query_string: LiteralString,
table_name: LiteralString,
) -> None:
run_query("SELECT * FROM students") # ok
run_query(query_string) # ok
run_query("SELECT * FROM " + table_name) # ok
run_query(arbitrary_string) # type checker error
run_query( # type checker error
f"SELECT * FROM students WHERE name = {arbitrary_string}"
)
rm -rf
. А PEP 675 можно почитать здесь.4) Data class transforms
Декоратор который декорирует класс, метакласс или функцию которые являются декоратором. Получившийся декоратор умеет показывать тайпчекеру что декорируемый объект имеет фичи как у датакласса. Причина создания такой штуки проста - нет стандартного пути обозначения, что какой-то объект имеет свойства, присущие датаклассу. Привет Pydantic! PEP 681 читать здесь.
5) Вариативные дженерики.
Есть такая штука как
TypeVar
- она позволяет создавать дженерик параметризированный одним типом. А если нам нужно параметризировать произвольное количество типов? Теперь появился TypeVarTuple
, который решает эту проблему.Зачем это нужно: мы все знаем, что всякие датасотонисты любят наш питон из-за обилия всяких инструментов по типу NumPy или Pandas. Вариативные дженерики позволяют параметризировать структуры, которые подобны массивам, что в свою очередь позволяет находить ошибки при операции с этими структурами тайпчекеру.
PEP 646 читать здесь.
#pep
Разговоры шли давно, но 9ого числа представили PEP 703, который предлагает сделать GIL опциональным. Прототип опубликован в репозитории nogil.
В качестве основания используется то, что Python используют для ML, а GIL - это серьезное препятствие для параллельных вычислений.
В этом PEP так же привели работу с PEP 684, который предлагает прекратить использовать GIL между несколькими интерпретаторами в процессе.
Как думаете, могут ли действительно убрать/сделать опциональным GIL?
#pep
В качестве основания используется то, что Python используют для ML, а GIL - это серьезное препятствие для параллельных вычислений.
В этом PEP так же привели работу с PEP 684, который предлагает прекратить использовать GIL между несколькими интерпретаторами в процессе.
Как думаете, могут ли действительно убрать/сделать опциональным GIL?
#pep
Python Enhancement Proposals (PEPs)
PEP 703 – Making the Global Interpreter Lock Optional in CPython | peps.python.org
CPython’s global interpreter lock (“GIL”) prevents multiple threads from executing Python code at the same time. The GIL is an obstacle to using multi-core CPUs from Python efficiently. This PEP proposes adding a build configuration (--disable-gil) to...
В PEP 695 предлагают наконец переделать синтаксис для указания дженериков и ввести новый оператор для указания алиасов.
1) Что там с дженериками?
Например, если раньше было так:
Раньше алиасы типов записывались вот так:
#pep
1) Что там с дженериками?
Например, если раньше было так:
_T_co = TypeVar("_T_co", covariant=True, bound=str)То сейчас предлагают сделать так:
class ClassA(Generic[_T_co]):
def method1(self) -> _T_co:
...
class ClassA[T: str]:2) А что с алиасами?
def method1(self) -> T:
...
Раньше алиасы типов записывались вот так:
_T = TypeVar("_T")Сейчас предлагают сделать вот так:
ListOrSet: TypeAlias = list[_T] | set[_T]
type ListOrSet[T] = list[T] | set[T]Если не ошибаюсь, то ждем в 3.12, PEP уже приняли.
#pep
Python Enhancement Proposals (PEPs)
PEP 695 – Type Parameter Syntax | peps.python.org
This PEP specifies an improved syntax for specifying type parameters within a generic class, function, or type alias. It also introduces a new statement for declaring type aliases.
Появился PEP 723, который предлагает "встраивать"
Предлагается добавить переменную
К примеру, вот так будет выглядеть скрипт, которому для работы нужна библиотека
#pep
pyproject.toml
в однофайловые скрипты. Предлагается добавить переменную
__pyproject__
, которая будет содержать в себе валидный TOML, описывающий метадату скрипта, в том числе как скрипт запускать и какие зависимости необходимы для запуска.К примеру, вот так будет выглядеть скрипт, которому для работы нужна библиотека
requests
и питон 3.11 или выше:__pyproject__ = """PEP прикольный, что-то такое есть в качестве экспериментального RFC в Rust. Из минусов хотел бы отметить то, что автоматическая установка зависимостей может привести к запуску нежелательного кода. Но решение банальное - перед тем как что-то запускать, проверяйте, что вы запускаете.
[project]
requires-python = ">=3.11"
dependencies = [
"requests<3",
]
"""
import requests
resp = requests.get("https://peps.python.org/api/peps.json")
print(resp.json())
#pep
Python Enhancement Proposals (PEPs)
PEP 723 – Inline script metadata | peps.python.org
This PEP specifies a metadata format that can be embedded in single-file Python scripts to assist launchers, IDEs and other external tools which may need to interact with such scripts.
Тианголо (создатель FastAPI) предложил новый PEP 727, который позволяет стандартизировать механизм документирования параметров.
Причина проста - существует много псевдо-стандартов по форматированию параметров в docstring (например свои стандарты есть у numpy, гугла, много их!), но не все редакторы/IDE имеют возможность поддерживать эти "микроязыки". Он предлагает стандартизировать подход, используя существующий мощный инструмент в виде аннотаций типов.
Основное предложение - добавление в
А вот как это будет выглядеть:
Выглядит интересно, но важно понимать - автор пытается создать ещё один стандарт. Поддержит ли его комьюнити и уйдет ли PEP в работу? Остается только гадать.
#pep
Причина проста - существует много псевдо-стандартов по форматированию параметров в docstring (например свои стандарты есть у numpy, гугла, много их!), но не все редакторы/IDE имеют возможность поддерживать эти "микроязыки". Он предлагает стандартизировать подход, используя существующий мощный инструмент в виде аннотаций типов.
Основное предложение - добавление в
typing
новой функции doc
, которая принимает единственный параметр documentation
. Ожидается, что эта функция будет использоваться вместе с Annotated
.А вот как это будет выглядеть:
def create_user(Тианголо заранее позаботился и о старых версиях - он не стал выдумывать новый синтаксис, так же предлагается добавить
lastname: Annotated[str, doc("The **last name** of the newly created user")],
firstname: Annotated[str | None, doc("The user's **first name**")] = None,
) -> Annotated[User, doc("The created user after saving in the database")]:
"""
Create a new user in the system, it needs the database connection to be already
initialized.
"""
pass
doc()
в пакет typing_extensions
, который используют старые версии питона для исключения проблем с совместимостью. Выглядит интересно, но важно понимать - автор пытается создать ещё один стандарт. Поддержит ли его комьюнити и уйдет ли PEP в работу? Остается только гадать.
#pep
Python Enhancement Proposals (PEPs)
PEP 727 – Documentation in Annotated Metadata | peps.python.org
This PEP proposes a standardized way to provide documentation strings for Python symbols defined with Annotated using a new class typing.Doc.
Пока я спал, руководящий совет языка принял PEP 703 (Making the Global Interpreter Lock Optional in CPython).
Кратко о том, о чём говорится в посте:
1. Руководящему совету ясно, что несмотря на все проблемы и недостатки потоков, nogil будет полезен для Python, так как позволит находить более масштабируемые решения.
2. В то же время, они не уверены, получится ли убрать GIL не сломав при этом обратную совместимость - всё же не хотелось бы терять десятилетия развития базы пакетов. Существующая пакетная экосистема - это одна из сильных сторон языка, как и простая интеграция библиотек на C c CPython.
3. Оценить влияние nogil без реализации сложно, поэтому nogil должен выпускаться в составе регулярных релизов и не обязательно он там должен быть по-умолчанию.
4. Это всё ещё не гарантированная история. Если что-то пойдет не так - от изменений откажутся. Развёртывание должно быть постепенным и наиболее плавным.
5. Выкатка будет происходить в 3 фазы, которые возможно изменятся:
- В первой фазе nogil сделают возможным таргетом при сборке, чтобы разработчики могли тестировать свои пакеты.
- Во второй фазе, когда изменения в API и ABI будут сформированы, а поддержка nogil от сообщества будет достаточной, nogil-сборку добавлят как "поддерживаемую, но не по умолчанию".
- В третьей фазе nogil-сборку сделают сборкой "по-умолчанию", а от gil-сборки будут отказываться.
6. При успешной реализации nogil, ожидается падение производительности на 10-15% в худшем случае.
#pep
Кратко о том, о чём говорится в посте:
1. Руководящему совету ясно, что несмотря на все проблемы и недостатки потоков, nogil будет полезен для Python, так как позволит находить более масштабируемые решения.
2. В то же время, они не уверены, получится ли убрать GIL не сломав при этом обратную совместимость - всё же не хотелось бы терять десятилетия развития базы пакетов. Существующая пакетная экосистема - это одна из сильных сторон языка, как и простая интеграция библиотек на C c CPython.
3. Оценить влияние nogil без реализации сложно, поэтому nogil должен выпускаться в составе регулярных релизов и не обязательно он там должен быть по-умолчанию.
4. Это всё ещё не гарантированная история. Если что-то пойдет не так - от изменений откажутся. Развёртывание должно быть постепенным и наиболее плавным.
5. Выкатка будет происходить в 3 фазы, которые возможно изменятся:
- В первой фазе nogil сделают возможным таргетом при сборке, чтобы разработчики могли тестировать свои пакеты.
- Во второй фазе, когда изменения в API и ABI будут сформированы, а поддержка nogil от сообщества будет достаточной, nogil-сборку добавлят как "поддерживаемую, но не по умолчанию".
- В третьей фазе nogil-сборку сделают сборкой "по-умолчанию", а от gil-сборки будут отказываться.
6. При успешной реализации nogil, ожидается падение производительности на 10-15% в худшем случае.
#pep
Discussions on Python.org
PEP 703 (Making the Global Interpreter Lock Optional in CPython) acceptance
(Posted for the whole Steering Council.) As we’ve announced before, the Steering Council has decided to accept PEP 703 (Making the Global Interpreter Lock Optional in CPython) . We want to make it clear why, and under what expectations we’re doing so. It…