动态添加字段到数据类对象

Dynamically add fields to dataclass objects

我正在编写一个库来访问 REST API。它 returns json 与用户对象。我将它转换为字典,然后将其转换为数据类对象。问题是并非所有字段都是固定的。我想动态添加其他字段(未在我的数据类中指定)。我可以简单地为我的对象赋值,但它们不会出现在对象表示中并且 dataclasses.asdict 函数不会将它们添加到生成的字典中:

from dataclasses import asdict, dataclass

@dataclass
class X:
    i: int

x = X(i=42)
x.s = 'text'

x
# X(i=42)

x.s
# 'text'

asdict(x)
# {'i': 42}

您可以使用 make_dataclass 即时创建 X

X = make_dataclass('X', [('i', int), ('s', str)])
x = X(i=42, s='text')

asdict(x)
# {'i': 42, 's': 'text'}

或派生 class:

@dataclass
class X:
    i: int

x = X(i=42)
x.__class__ = make_dataclass('Y', fields=[('s', str)], bases=(X,))
x.s = 'text'

asdict(x)
# {'i': 42, 's': 'text'}

如前所述,标记为可选的字段应该可以解决问题。如果没有,请考虑使用 dataclasses 中的属性。是的,常规属性应该工作得很好——尽管你必须在 __post_init__ 中声明字段,这有点不方便。

如果您想为 属性 设置默认值,那么在创建对象后立即访问 getter 就可以正常工作,并且如果您还希望能够通过构造函数设置默认值,您可以使用一个称为字段属性的概念; dataclass-wizard 等几个库提供 全力支持。

用法示例:

from dataclasses import asdict, dataclass
from typing import Optional

from dataclass_wizard import property_wizard


@dataclass
class X(metaclass=property_wizard):
    i: int
    s: Optional[str] = None

    @property
    def _s(self):
        return self._s

    @_s.setter
    def _s(self, s: str):
        self._s = s


x = X(i=42)
x.s = 'text'

x
# X(i=42, s='text')


x.s
# 'text'

asdict(x)
# {'i': 42, 's': 'text'}

免责声明:我是这个库的创建者(和维护者)。