Находки в опенсорсе
12.8K subscribers
23 photos
2 videos
3 files
870 links
Привет!

Меня зовут Никита Соболев. Я занимаюсь опенсорс разработкой полный рабочий день.

Тут я рассказываю про #python, #c, #opensource и тд.
Поддержать: https://boosty.to/sobolevn
РКН: https://vk.cc/cOzn36

Связь: @sobolev_nikita
Download Telegram
PEPы в Python окончательно вышли из-под контроля

Давайте посмотрим, что происходит с ПЕПами в CPython. Там много новых спорных штук.
Начнем с более базовых, перейдем к дичи в конце. Какие-то ПЕПы приняты, но большинство в обсуждении.

Докстринги для TypeAliasType

PEP-846: https://github.com/python/peps/pull/5116

Базовая база: пишем докстринги после ключевого слова type - у нас появляется __doc__ атрибут.


type Timeout = float | None
"""Maximum wait in seconds. """


Привычный синтаксис из-за sphinx аннотаций для атрибутов.
Кстати, поддержка правила для поиска докстрингов вне правильных мест уже в wps!

Паттерн-матчинг конкретных значений

PEP-845: https://github.com/python/peps/pull/5107

В питоне была проблема, что нельзя сматчить конкретное значение из переменной. Все имена в PM всегда переписываются. В первой версии PEP-622 хотели сделать паттерны для сравнения с переменной, но потом отказались. А без такого - жить довольно сложно.

Такой синтаксис предлагают авторы:


def get_book_titles_for_author(author: str):
for book in BOOKS:
match book:
case {"title": title, "author": .author}:
yield title


Обратите внимание на .author, что показывает матч со значением внутри author, а не переназначение переменной author. Если бы добавили $ для "констант", то было $author 🌚
Мне нравится, выглядит полезно.

yield from в асинхронных генераторах

PEP-828: с python3.16 можно будет писать так:


async def agenerator():
yield 1
yield 2
return 3

async def main():
result = yield from agenerator()
assert result == 3


Я нейтрален, зависит от сложности реализации и граничных случаев.

Явные public и private декораторы

PEP 844:


# spam.py
@public
class Public:
...

@private
class Private:
...

# ex.py
import spam
spam.__all__ # ['Public']


Манипуляция __all__ через декоратор. А можно не надо?
Почему? __all__ используется для from spam import * и не для чего больше. __all__ надо закапывать, а не развивать. Более того, декоратор нельзя повесить на имена и тайп-алиасы. Кажется очень непродуманным решением.

Ключевое слово export

PEP-843: Предлагают добавить ключевое слово export для ... я не знаю чего.
А, опять манипуляции __all__. Чем не устраивает простая текущая система? Если имя начинается с _ - то оно protected. Ключевое слово для управления списком! Я против.

Ребята из FastAPI тащат синтаксис для себя в stdlib

PEP-835: Предлагают сделать @ типовым и рантайм оператором для создания Annotated объектов.
Крайне неудачный PEP на мой взгляд, о чем я написал авторам и собрал кучу поддержки.
Не поймите меня неправильно: я всячески за операции над типами. Просто я не думаю, что int @ Field(max=100) должно значить Annotated[int, Field(max=100)]. Нет задачи сократить количество символов, которые мы пишем (а некоторые уже и не пишут).

Одной строкой

- На прошлой неделе я побывал в пресс-туре MAGNIT TECH в Суздале. Было очень круто. Приятно видеть, как развивается ритейл. Обсудил с коллегами умные кассы, внедрение ИИ, новые способы оплаты, предиктивную аналитику спроса, интересное в логистике, предложил им внедрить wps. Хорошо провел время с коллегами @alexgladkovblog, @t0digital, @MrTeamlead. Суздаль - очень красивый! Кароч, очень понравилось. Спасибо за приглашение!
- Мы релизнули dmr@0.15.0 в рамках #opensource_september, все большое спасибо за участие. Наш самый большой релиз. Пока что!
- Про PEP-805 будет отдельный пост
- В Нижний на конфу уже собралось очень много людей из разных городов, приезжайте и вы! Можно даже отбивку о регистрации не ждать, всех пустим :)

Обсуждение: Как вам данные ПЕПы? Нашли что-то полезное для себя?
🔥56❤12🤔12👍11👌6🎉1
Монадические выражения в Python. Наконец-то!

Продолжаем разговор про интересные PEPы. Поговорим сразу про два:
- PEP-823: https://peps.python.org/pep-0823
- PEP-824: https://peps.python.org/pep-0824

В целом они оба об одном: использовании ? для решения проблемы обращения к None при работе с данными.

Первый PEP описывает два новых оператора ?. и ?[], которые позволяют представить выражение some?.field как:


if some is not None:
field = some.field
else:
field = None


Аналогично: some?[field] будет делать тоже самое, но для для some[field].

Второй - позволяет использовать оператор ?? вместо is not None и тернарных выражений. Теперь мы сможем писать some ?? 'default' вместо some if some is not None else 'default'. И есть вариант ??= по аналогии с +=, тд.

Данная попытка уже не первая. Первая была сделана очень много лет назад в PEP-505, который отклонили.
Но теперь, два данных PEP'а проспонсированы лично Гвидо, так что шансы хорошие.

Примеры

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


def get_customer_name(data: Data) -> str | None:
"""Get customer name in lower case if it exists."""
customer = data.customer
if customer is not None:
user = customer.user
if user is not None:
return user.name.lower()
return None


Превращается в:


def get_customer_name(data: Data) -> str | None:
return data.customer?.user?.name.lower()


Как будет работать второй вариант? Если data.customer является None, то мы сразу его возвращаем. Если нет, пробуем получить .user, проверяем его на None. И тд.

Важный момент: __getattr__ и __getitem__ никак не меняются, они просто не вызываются при None.

В большинстве языков (PHP/JS/TS/C#/Kotlin/Swift/Rust/Dart) такая фича уже есть, она делает работу с вложенными опциональными данными сильно удобнее.

Типизация

Ничего не меняется:
- get_customer_name все еще возвращает str | None
- Обращение через . к optional полю - все еще ошибка
- Обращение через ?. к optional полю - не ошибка, а просто None

Перформанс

Самое интересно! Первый вариант get_customer_name выполняет много опкодов на ровном месте.
Условия, сравнения, прыжки, LOAD_ATTR и тд. Что делает данный код сложным для оптимизации и JIT'ирования. Но data.customer?.user?.name.lower() оптимизировать очень удобно, потому что можно сделать один новый опкод LOAD_OPTIONAL_ATTR (или добавить еще один oparg к текущему LOAD_ATTR), а уже его будет очень удобно оптимизировать. Потому что весь код проверок будет жить в одном месте рядом на C, а не куча условий на питоне. И последовательность таких LOAD_OPTIONAL_ATTR будет удобно находить и возможно оптимизировать в том числе.

Почему монадические?

Потому что на заголовок нужно было как-то забайтить! 🌚
Но и контекст, конечно, реально существует. Например в dry-python/returns уже много лет была доступна конструкция Maybe с методом .bind, который ведет себя прямо как ?. оператор и не продолжает выполнение после первого None / Nothing.

Как вы уже поняли, я дикий фанат таких штук. Ждем всем чатом!

Одной строкой

- dmr@0.16.0 почти готов; изменений просто капец сколько. Каждая часть фреймворка вылизывается и становится на порядок лучше. Релиз в конце #opensource_september
- Наша бесплатная конференция 17 октября в Нижнем Новгороде получила двух новых спикеров к 6 текущим. Итого: 8 докладов от топовых питон ютюберов и опенсорсеров! Анонс новых докладов будет в самое ближайшее время. А пока можно регистрироваться
- Обратите внимание, что ждать подтверждения не нужно! Мы стараемся всем сразу высылать письма, но они нужны только для моральной поддержки :) Было много вопросов по статусу письма. Если вы зарегались, то можете приходить! Пустим всех.

Обсуждение: Что вы думаете? Не возникает ли у вас вопросиков по данной фиче? Как вы сейчас решаете данную проблему с boilerplate кодом?
2🔥143❤27👍16🤔9👎6🤮5😁1