【问题标题】:How to include ClassVars in dataclass asdict() output?如何在数据类 asdict() 输出中包含 ClassVars?
【发布时间】:2021-03-05 18:22:36
【问题描述】:

我有像这样的带有静态字段的数据类:

from typing import ClassVar
from dataclasses import dataclass, asdict

@dataclass
class X:
  static_field: ClassVar[str] = "static_value"
  normal_field: str

@dataclass
class Y:
  x: X

y = Y(x=X(normal_field="normal_value"))
asdict(y) # yields {'x': {'normal_field': 'normal_value'}}

如何使static_field 成为输出的一部分? static_field 字段应该永远在实例化类时设置。

【问题讨论】:

  • 为什么您希望它们包含在返回的字典中?
  • 我正在创建一些数据类,用于序列化/反序列化一些 json 数据。为了填充正确的数据类,有时我需要一个对象上的 "type": "enum""type": "struct" 字段。本质上,存在与不应更改的数据类耦合的识别字段

标签: python python-dataclasses


【解决方案1】:

来自docs

如果一个字段是一个ClassVar,它被排除在一个字段之外并且被数据类机制忽略。模块级的fields() 函数不会返回此类ClassVar 伪字段。

所以,我认为这是不可能的。您可能需要重新考虑设计的那一部分。

【讨论】:

    【解决方案2】:

    这个解决方案使用了一个未记录的特性,__dataclass_fields__ 属性,但它至少在 Python 3.9 中有效:

    from dataclasses import dataclass
    from typing import Dict, Any, ClassVar
    
    def asdict_with_classvars(x) -> Dict[str, Any]:
        '''Does not recurse (see dataclasses._asdict_inner() for how to do that
        right), and fails if x lacks a class variable declared in x's class
        definition.'''
        return dict(
            (name, getattr(x, name))
                for name in x.__dataclass_fields__
        )
    
    @dataclass
    class Blah:
        x: int
        y: ClassVar[str] = 'the classvar'
    
    print(asdict_with_classvars(Blah(22)))
    

    输出:

    {'x': 22, 'y': 'the classvar'}
    

    如果 ClassVar 在抽象类中声明但未定义,则可能会创建一个没有 ClassVar 值的实例。在这种情况下,对getattr() 的调用将引发AttributeError。但要处理它并根据自己的需要定制它并不难。

    【讨论】:

      猜你喜欢
      • 2019-11-12
      • 2021-02-22
      • 2022-11-03
      • 1970-01-01
      • 2020-08-03
      • 1970-01-01
      • 1970-01-01
      • 2014-11-22
      • 2019-07-21
      相关资源
      最近更新 更多