#python #парсер #python_35
Есть класс: class MyClass: __slots__ = ('foo', 'bar') Есть объект: obj = MyClass() И есть желание присвоить полям объекта значения разом: obj.__something__ = ('foovalue', 202) # Распаковка из кортежа прямиком в поля объекта Можно просто явно указать имена полей: obj.foo, obj.bar = ('foovalue', 202) Но если бы был способ распаковки значении без явного указания имён полей это бы сильно сократило количество кода. На данный момент приходится писать так: class XBGHeader: __slots__ = ( 'id', '_0', 'block_size', 'data_size', 'has_block_inside', ) @staticmethod def parse(stream): obj = XBGHeader() fmt = '=4s4I' fmt_size = calcsize(fmt) # Это место меня огорчает =( ( obj.id, obj._0, obj.block_size, obj.data_size, obj.has_block_inside, ) = unpack(fmt, stream.read(fmt_size)) Можно и функцию написать: def setattrs(attrs, obj, values): # Присваивает список значении списку полей указанного объекта for attr, value in zip(attrs, values): setattr(obj, attr, value) И приходилось бы писать так: setattrs(obj.__slots__, obj, unpack(fmt, stream.read(fmt_size))) Но хотелось бы pythonic решения этой задачи =) Спасибо!!!
Ответы
Ответ 1
В таких случаях удобно использовать namedtuple: from collections import namedtuple XBGHeader = namedtuple('XBGHeader', ('id', 'us_0', 'block_size', 'data_size', 'has_block_inside') ) obj = XBGHeader(*unpack(fmt, stream.read(fmt_size)) # распаковка в вашем случае test_obj = XBGHeader(*(42, 0, 1024, 8192, 'foo')) print(test_obj) # XBGHeader(id=42, us_0=0, block_size=1024, data_size=8192, has_block_inside='foo') P.S. поля в namedtuple не могут начинаться с нижнего подчеркивания. Для версий Python 3.7 и старше можно использовать dataclass, который является почти альтернативой namedtuple с допольнительными возможностями. from dataclasses import dataclass from typing import Any @dataclass class XBGHeader: _id: int _0: Any block_size: int data_size: int has_block_inside: bool print(XBGHeader(42, 'bar', 1024, 8192, False)) # XBGHeader(_id=42, _0='bar', block_size=1024, data_size=8192, has_block_inside=0)Ответ 2
Руководство по магическим методам в Питоне class XBGHeader: def __init__(self, slots, *args): self.slots = slots self.__dict__.update(zip(slots, args)) return def __getattr__(self, attr): if attr in self.slots: return None else: raise AttributeError(attr) slots = ( 'id', '_0', 'block_size', 'data_size', 'has_block_inside', ) ob = XBGHeader(slots, 1, 2) print(ob.id) print(ob._0)
Комментариев нет:
Отправить комментарий