簡體   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