繁体   English   中英

Python 数据类实现选择类型

[英]Python dataclass to implement choice type

我有一组数据类说:

    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
    

当我做:

c = Container(Item(name="item-1"), cid=10)
asdict(c)

我得到:

{'item': {'name': 'item-1', 'identifier': None},'cid': 10,'cname': None}

但在我的模式中, Item是“选择”类型,所以我只想在“asdict”中包含“名称”或“标识符”,具体取决于实际设置的那些(仅适用于 Item 类型)。

就像是:

{'item': {'name': 'item-1'},'cid': 10,'cname': None}

或者:

{'item': {'identifier': 'id-1'},'cid': 10,'cname': None}

我的原始代码要复杂得多,而且关系更加嵌套,所以我正在寻找一种可以应用于特定数据类的解决方案。 我尝试操纵__dict__以在__post_init__中添加属性,但这没有用。 例如我试过

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)

但那会打印

{'item': {}, 'cid': 10, 'cname': None}

这可能不是您想要的,但此时,当您想要数据类的自定义dict表示时,唯一的.asdict dataclass

这是一个建议的起点(可能需要调整):

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}

我没有使用值列表对其进行测试,但请尝试以下方法:

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}

已验证DC:https://github.com/EvgeniyBurdin/validated_dc

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM