Веб-версияОткрыть в Telegram

ПостТам в Python 3.12 добавили нашумевший PEP 659, а у меня пет-проект один давно не обновлялся, и так уж звёзды сошлись, чт…

11 мая 2024
К
Коробка с питоном
Там в Python 3.12 добавили нашумевший PEP 659, а у меня пет-проект один давно не обновлялся, и так уж звёзды сошлись, что я сижу второй день обновляю его на 3.12 Задача - есть функционал, который под капотом имеет некоторый класс следующего вида: class BaseFunction: serialize_to: None def serialize(self, data: dict) -> serialize_to: pass # тут мы используем наш serialize_to @dataclass class ModelA: x: str class FunctionA(BaseFunction): serialize_to: ModelA Мы определяем новые классы наследуясь от BaseFunction, переопределяем в них serialize_to и вызываем serialize который делает нам инстанс serialize_to. Ну прямо дженерик напрашивается! Тем более в 3.12 их завезли, красивые: class BaseFunction[T]: def serialize(self, data: dict) -> T: pass # тут мы используем наш serialize_to class FunctionA(BaseFunction[ModelA]): pass Встаёт вопрос, а как нам получить наш тип из дженерика? Для начала, получим __orig_bases__[0] - он вернёт нам классы, от которых мы наследовались. Так как нам нужен только наш первый класс, мы указываем [0]: >>> FunctionA.__orig_bases__ __main__.BaseFunction[__main__.ModelA] Ещё можно это сделать с помощью get_original_bases из types, но его добавили только в 3.12 (почему я об этом сказал - узнаете ниже). Теперь надо получить получить сам тип в дженерике. В этом нам поможет typing.get_args, который получает все аргументы типа. Дополнительно укажем, что нам нужен первый тип: >>> get_args(FunctionA.__orig_bases__[0])[0] <class '__main__.ModelA'> Теперь в методе serialize класса BaseFunction[T] можно написать штуку, которая автоматически сериализует наши данные: def serialize(self, data: dict) -> T: type_from_generic = get_args(self.__class__.__orig_bases__[0])[0] return type_from_generic(**data) Проверяем: >>> f = FunctionA() >>> f.serialize(data={"x": 1}) ModelA(x=1) Вы восхитительны! Кстати, эта же штука должна работать ещё вроде как аж с 3.8, так как в нём именно был добавлен __orig_bases__ (PEP 560), ну и под капотом у новых дженериков используется... >>> FunctionA.__mro__ (<class '__main__.FunctionA'>, <class '__main__.BaseFunction'>, <class 'typing.Generic'>, <class 'object'>) Ага, typing.Generic :) #рецепт #std
11 · 1.1K ·

Рядом в ленте

ККоробка с питономПодписчиков набежало, а постов всё так же не было. Буду исправляться! Сегодня расскажу про deptry - тулзу, которая позволяет находить неиспользованные, транзитиККоробка с питономDishka - IoC-контейнер для Python Когда мы следуем подходу Dependency Injection, а особенно - слоистой архитектуре, у нас образуется отдельная группа функций и
это сообщение
ККоробка с питономДа, оно существует. Под капотом низкоуровневая магия, из самого понятного - оно позволяет создавать поддельные объекты на куче. Можно создать байтовый массив с ККоробка с питономИтак, ко мне пришли ребята из Podlodka Python Crew и предложили разыграть один бесплатный билет на новый сезон их конференции, где участников с 3 по 7 июня буде
ККоробка с питономКоробка с питоном@boxwithpython · канал · Технологии
488подписчиков154постов в индексе
Лента площадки Открыть в Telegram

Открытая публичная лента из поискового индекса ChatCrawler — «Google по публичному Telegram»; обновляется по мере обхода площадки. Время — UTC.

Только публичный контент, официальный API Telegram. О проекте · Вопросы · Чего мы не делаем · Убрать страницу из выдачи · Каталог · Поиск · Как мы считаем