3

我有这个嵌套字典类,我需要将其实例转储到 YAML

class NestedDict(dict):
    """Implementation of perl's autovivification feature."""
    def __getitem__(self, item):
        try:
            return dict.__getitem__(self, item)
        except KeyError:
            value = self[item] = type(self)()
            return value

在转储这本词典时:

pyaml.dump(nesteddict)

我收到此错误(仅发布了整个消息对象的摘录):

“RepresenterError:无法表示对象:{'a1401': 'ts755', 'ts64': {'topic': {'a1561': 'Process Control'}}, 'a1450': 'ts107', 'a1609': 'ts341','a1400':'ts753',......

那么如何在 YAML 中巧妙地表示这一点?我读到 PyYAML 确实支持嵌套递归结构。

4

1 回答 1

2

YAML 确实支持嵌套递归结构:

import ruamel.yaml

data = [1, 3]
data.append(data)

print ruamel.yaml.dump(data)

将为您提供带有锚点 ( &id001) 和引用 ( *id001) 的 YAML:

&id001
- 1
- 3
- *id001

并且您的 a 的简单导数dict可以被丢弃,至少使用ruamel.yaml 也没有问题¹:

import ruamel.yaml

class NestedDict(dict):
    """Implementation of perl's autovivification feature."""
    def __getitem__(self, item):
        try:
            return dict.__getitem__(self, item)
        except KeyError:
            value = self[item] = type(self)()
            return value

data = NestedDict(a=1, b=2)
data['c'] = data

print ruamel.yaml.dump(data)

这给了你:

&id001 !!python/object/new:__main__.NestedDict
dictitems:
  a: 1
  b: 2
  c: *id001

如果您需要更复杂的表示,例如过滤掉一些 dict 值,您必须告诉 ruamel.yaml 如何表示您的对象。要告诉它 NestedDict 有一个表示器,您可以将其设为 的子类ruamel.yaml.YAMLObject,提供类属性yaml_tag = "!NestedDict"并实现__repr__();或者您可以提供一个明确的代表。

后者是内部使用的,IMO 更容易实现,因为您可以通过返回对象的字典表示(即顶级键值对)来搭载字典代码。

def nested_dict_representer(dumper, node):
    return dumper.represent_mapping("!NestedDict", xyz)

xyz您的对象的一些键值对表示形式在哪里。


¹免责声明:我是该软件包的作者,它是 PyYAML 的增强版本。

于 2015-06-08T07:30:57.547 回答