[英]Python dataclass to implement choice type
I have a set of dataclasses say:我有一组数据类说:
from dataclasses import dataclass, asdict, InitVar
@dataclass
class Item:
name: str = None
identifier: int = None
@dataclass
class Container:
item: Item
cid: int
cname: str = None
When I do:当我做:
c = Container(Item(name="item-1"), cid=10)
asdict(c)
I get:我得到:
{'item': {'name': 'item-1', 'identifier': None},'cid': 10,'cname': None}
But in my schema Item is a "choice" type so I only want to include "name" or "identifier" in "asdict" depending on which of those are actually set (ONLY for Item type).但在我的模式中, Item是“选择”类型,所以我只想在“asdict”中包含“名称”或“标识符”,具体取决于实际设置的那些(仅适用于 Item 类型)。
something like:就像是:
{'item': {'name': 'item-1'},'cid': 10,'cname': None}
OR:或者:
{'item': {'identifier': 'id-1'},'cid': 10,'cname': None}
My original code is much more complex and the relationships are more nested so I'm looking for a solution which I can apply to the specific dataclass.我的原始代码要复杂得多,而且关系更加嵌套,所以我正在寻找一种可以应用于特定数据类的解决方案。 I tried manipulating the
__dict__
to add attributes in __post_init__
but that didn't work.我尝试操纵
__dict__
以在__post_init__
中添加属性,但这没有用。 For eg I tried例如我试过
from dataclasses import dataclass, asdict, InitVar
@dataclass
class Item:
name: InitVar[str] = None
identifier: InitVar[int] = None
def __post_init__(self, name, identifier):
if name:
self.name = name
elif identifier:
self.identifier = identifier
print(self.__dict__)
@dataclass
class Container:
item: Item
identifier: int
cname: str = None
c = Container(Item(name="item-1"), cid=10)
asdict(c)
but that prints但那会打印
{'item': {}, 'cid': 10, 'cname': None}
It is probably not what you want, but at this time the only way forward when you want a customized dict
representation of a dataclass
is to write your own .asdict
method.这可能不是您想要的,但此时,当您想要数据类的自定义
dict
表示时,唯一的.asdict
dataclass
。
Here's a suggested starting point (will probably need tweaking):这是一个建议的起点(可能需要调整):
from dataclasses import dataclass, asdict
@dataclass
class DataclassAsDictMixin:
def asdict(self):
d = asdict(self)
for field, value in ((f,v) for f,v in vars(self).items() if f in d):
try:
value = value.asdict()
except AttributeError:
pass
else:
d.update([(field, value)])
return d
@dataclass
class Item:
name: str = None
identifier: int = None
def asdict(self):
d = asdict(self)
for k,v in d.copy().items():
if v is None:
del d[k]
return d
@dataclass
class Container(DataclassAsDictMixin):
item: Item
cid: int
cname: str = None
if __name__ == "__main__":
c1 = Container(Item(name="item-1"), cid=10)
assert c1.asdict() == {'item': {'name': 'item-1'}, 'cid': 10, 'cname': None}
c2 = Container(Item(identifier="id-1"), cid=10)
assert c2.asdict() == {'item': {'identifier': 'id-1'}, 'cid': 10, 'cname': None}
I haven't tested it with a list of values, but try this approach:我没有使用值列表对其进行测试,但请尝试以下方法:
from copy import copy
from dataclasses import dataclass, fields
from validated_dc import ValidatedDC
@dataclass
class Base(ValidatedDC):
def is_correct_value(self, value):
return True
def as_dict(self):
result = {}
nested = tuple(self.get_nested_validated_dc())
for field in fields(self):
value = copy(getattr(self, field.name))
if isinstance(value, list):
for item in value:
if isinstance(item, nested):
item = item.as_dict()
if isinstance(value, nested):
value = value.as_dict()
if self.is_correct_value(value):
result[field.name] = value
return result
@dataclass
class ItemBase(Base):
def is_correct_value(self, value):
return False if value is None else True
@dataclass
class Item(ItemBase):
name: str = None
identifier: int = None
@dataclass
class Container(Base):
item: Item
cid: int
cname: str = None
c = Container(Item(name="item-1"), cid=10)
assert c.as_dict() == {'item': {'name': 'item-1'}, 'cid': 10, 'cname': None}
ValidatedDC: https://github.com/EvgeniyBurdin/validated_dc已验证DC:https://github.com/EvgeniyBurdin/validated_dc
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.