无法将自定义词典写入 YAML

Cannot write custom dictionaries to YAML

我有使用三个嵌套的 python 代码 类:

@dataclass
class PanelGroup:
    num_panels: int
    panel_efficiency: float
    panel_surface: float
    elevation: int


class PanelString(dict[str, PanelGroup]):
    pass


class SolarInstallation(dict[str, PanelString]):
    pass

我从我的代码中静态创建这些 类 实例的方式是:

solar_installation = SolarInstallation(
        SSW_12=PanelString(G1=PanelGroup(4, 0.191, 1.705, 50),
                           G2=PanelGroup(5, 0.191, 1.705, 50)))

我想使此配置来自 YAML 文件,因此我尝试使用以下代码片段将正确的 YAML 内容转储到文件中:

yaml = ruamel.yaml.YAML()
yaml.register_class(SolarInstallation)
yaml.register_class(PanelString)
yaml.register_class(PanelGroup)
yaml.dump(solar_installation, sys.stdout)

但我唯一得到的是一个空字典:

!SolarInstallation {}

我做错了什么?

您需要告诉 ruamel.yaml 如何转储您的 类,只是注册不是 够了:

import sys
from dataclasses import dataclass
import ruamel.yaml


@dataclass
class PanelGroup:
    num_panels: int
    panel_efficiency: float
    panel_surface: float
    elevation: int

    @classmethod
    def to_yaml(cls, representer, node):
        d = {}
        for k in node.__annotations__:
            d[k] = node.__getattribute__(k)
        return representer.represent_mapping('!' + cls.__name__, d)

class PanelString(dict[str, PanelGroup]):
    @classmethod
    def to_yaml(cls, representer, node):
        return representer.represent_mapping('!' + cls.__name__, node)


class SolarInstallation(dict[str, PanelString]):
    @classmethod
    def to_yaml(cls, representer, node):
        return representer.represent_mapping('!' + cls.__name__, node)

solar_installation = SolarInstallation(
        SSW_12=PanelString(G1=PanelGroup(4, 0.191, 1.705, 50),
                           G2=PanelGroup(5, 0.191, 1.705, 50)))
yaml = ruamel.yaml.YAML()
yaml.register_class(SolarInstallation)
yaml.register_class(PanelString)
yaml.register_class(PanelGroup)
yaml.dump(solar_installation, sys.stdout)

给出:

!SolarInstallation
SSW_12: !PanelString
  G1: !PanelGroup
    num_panels: 4
    panel_efficiency: 0.191
    panel_surface: 1.705
    elevation: 50
  G2: !PanelGroup
    num_panels: 5
    panel_efficiency: 0.191
    panel_surface: 1.705
    elevation: 50