Наконец-то полезные фичи в питоне
Многие знают, что я почти не добавляю новые фичи в CPython, я стараюсь выпилить существующие и править баге в тех, что у меня не получается убирать. Новые если и добавляю, то без масштабных обсуждений.
Некоторые новые фичи встречают у меня сильный оптимизм: как новый встроенный sampling profiler. Вот тут видео про него кстати с прошедшего PyCon. Некоторые фичи встречают у меня понимание: как например typing.disjoint_base. Простая штука, решает понятную проблему. Некоторые фичи встречают у меня лютое подгорание: как например lazy imports. Вот доклад с пайкона и про них, кстати.
Я думаю, что мое понимание хорошей фичи очень сильно расходится с таким пониманием у других питонистов, мое понимание "хорошего питона" можно найти в моем wemake-python-styleguide.
Зная такую вводную, я решил сделать "большую" новую фичу. На один символ в грамматике.
Иммутабельному питону - быть!
У нас была довольно большая проблема: создавать мутабельные словари и множества - можно довольно легко. {1: 2} и {1, 2, 3}
Чтобы создать frozendict и frozenset нам уже нужен вызов функции: frozendict({1: 2}) и frozenset({1, ,2, 3}). Почему так делать не очень?
1. Потому что писать долго, мало людей будут заморачиваться. Зачем, когда проще создать мутабельную структуру? 2. Потому что frozendict и frozenset тупо медленнее. frozendict пока вообще имеет 0 оптимизаций для работы и просто в тупую копирует всю память из dict, который мы отправляем. Получая буквально O(n * 2) по памяти и времени работы. Делает лишний CALL. А frozenset({1, 2, 3}) немного оптимизирован через INTRINSIC_BUILD_FROZENSET опкод, который генерируется только для set в качестве входного аргумента 3. Неудобно писать comprehensions. Они получается сильно менее читаемые, чем их мутабельные версии
Мое предложение (пока только в формате обсуждения): https://discuss.python.org/t/frozenset-and-frozendict-comprehensions/101584/9 Мой PR с добавлением данной фичи в CPython: https://github.com/python/cpython/pull/152820 (он нужен для написания ПЕПа)
Как оно выглядит?
>>> ${1: 2} frozendict({1: 2}) >>> ${1, 2, 3} frozenset({1, 2, 3})
>>> ${x: x for x in range(3)} frozendict({0: 0, 1: 1, 2: 2}) >>> ${x for x in range(2)} frozenset({0, 1})
Что важно? Оно уже умеет все то, что умеют привычные нам конструкции без $: - ${} - пустой frozendict, как {} - пустой dict - ${1, *other} - распаковка внутри frozenset - ${**d for d in list_of_dicts} - распаковка внутри frozendict comprehension + PEP-798 - ${x async for x in async_iterable if x >0} - async frozenset comprehension с условием
Почему $? - Потому что $ - is the real deal 😎💸 - Потому что $ не имеет смысла сейчас: но будет значить "иммутабельность" - Потому что $ может легко в дальнейшем использовать для других иммутабельных штуках: $(x for x in range(1)) для нативного tuple comprehension, для PEP-805 с __freeze__ и тд
И другие новости моих опенсорс проектов одной строкой
- Новый релиз django-modern-rest с новыми DX фичами - Добавляем Token auth в следующий релиз DMR - msgspec готов к релизу новой версии с поддержкой frozendict - Улучшаем поддержку match/case в wemake-python-stylguide - Предлагаю улучшенное C-API для создания frozendict - Выпустил релиз punq с поддежкой типизации
Если вы хотите поддержать мою работу в опенсорсе: - https://boosty.to/sobolevn - https://github.com/sponsors/wemake-services
Обсуждение: Что вы думаете, нужен ли такой синтаксис? Удобнее ли будет пользоваться иммутабельными структурами после добавления такого синтаксиса?