Комментарии 35
Возможно тут дело в завышенных ожиданиях, я ожидал, что это будет нижний кирпич для построения различных штук для работы с данными, например, тех же orm, а получил еще один namedtuple, который я практически никогда не использую (потому что мне не лень пилить классы со слотами :) ), но еще и хуже реализованный.
Ну и сама реализация в духе «а давайте понапихаем методов в класс» не очень красивая, на мой взгляд. Мне бы куда больше понравилась реализация через мета-классы, опять же, потому что она расширяема.
Мне кажется, сами авторы довольны дизайном дата-классов. Вот выступление Реймонда Хеттингера по этому поводу. Про слоты он там тоже говорит — мол, жаль, что не получилось, в будущем, возможно, поддержим.
Авторы ставили перед датаклассами одни цели, я себе нафантазировал другие и вот получилось то, что получилось :)
А валидацию можно и прикрутить.
Когда впервые видишь дата-класс, хочется перейти на новую версию языка только ради него:
У меня промелькнула сперва мысль, что «да!, дейтсвительно хочется перейти на другую сторону улицы!»
Потом был когнитивный диссонанс. Датаклассы получились совсем не тем. Хотелось, ытобы на них можно было делать полноценный ORM, хотелось больше свободы управления типами, больше средств автоматизации для валидации, конвертации и сериализации. Получилось же, что теперь это всёё равно приходится впиливать вручную, но появляется еще одна «магическая» скрытая прослойка в виде декоратора, который «колдует» над моим классом.
В моём представлении главная проблема с namedtuples в отсутствии синтаксического сахара работы с словарями.
Если бы мы вместо foo["bar"]
могли бы писать foo.bar
, наша жизнь была бы восхитительной, и namedtuples не понадобились бы. Ансибл, например, так разрешил в шаблонах, и оно восхитительно.
foo = {bar = 42}
print(foo[«bar»], foo.bar)
class Bunch(dict):
def init(self, *args, *kwargs):
super().init(args, **kwargs)
self.dict = self
Затупил с форматированием, но идея должна быть понятна :)
- входящие данные могут запороть служебные свойства и методы, например keys() или dunder'ы.
- на некоторых версиях питона дёт утечку памяти
- ну и просто крайне неочевидно.
Так что, если нужен attrdict, лучше написать явную логику фильтрации ключей и хранить всё в отдельном словаре.
class Pet(namedtuple('BasePet', ('type', 'name', 'age'))):
@staticmethod
def __new__(cls, type, name='', age=1): #можно делать необязательные параметры
#тут можно делать преобразование типов или иную логику
type = str(type)
name = name if name else default_names.get(type, type)
return super(Pet, cls).__new__(cls, name, type, age)
Так происходит, потому что обычные объекты в питоне таскают с собой увесистый дандер __dict__
Если вы давно работаете с питоном, то наверняка знаете: легковесный объект можно создать через дандер __slots__:
Прошу простить мое невежество, но что за термин "дандер"?
Гугл (при попытке поиска) отсылает к домашнему самогоноварению :)
Почему вы считаете кортежи изобретением питона, при том что это математический термин, широко применявшийся в информатике например при описании реляционых баз данных, когда питона насколько я помню, еще не существовало? Возможно питон и был первым языком, где такое появилось, но тут уже мало кто может быть уверенным. Но базы данных точно были раньше, статьи Кодда датируются где-то 1970 годом.
Возможно питон и был первым языком, где такое появилось, но тут уже мало кто может быть уверенным.Не был. В детстве я читал про язык РАПИРА.
вряд ли мы найдем самый первый.Раньше LISP'а не так много языков было, но утверждать, что это он, не буду. ¯\_(ツ)_/¯
typing.NamedTuple
. Работает так же, выглядит прилично.
class A(typing.NamedTuple):
field: int
field_with_default: int = 3
Я даже задумался выкинуть пакет `dataclasses` из проекта на 3.6 питоне и полностью юзать именно этот вариант…
В 95% случаев, имхо, dataclasses
не нужны. Только если нужны мутабельные контейнеры — их на NamedTuple
не сделаешь. Плюс, в typing.NamedTuple
нельзя переопределять некоторые методы, а точнее:
# attributes prohibited to set in NamedTuple class syntax
_prohibited = ('__new__', '__init__', '__slots__', '__getnewargs__',
'_fields', '_field_defaults', '_field_types',
'_make', '_replace', '_asdict', '_source')
Кортеж здорового человека