我有这个嵌套的字典类,我的实例需要转储到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':'过程控制'}},'a1450':'ts107', 'a1609':'ts341','a1400':'ts753',......
那么如何在YAML中巧妙地代表这一点呢?我读到PyYAML确实支持嵌套的递归结构。
答案 0 :(得分:2)
YAML确实支持嵌套的递归结构:
import ruamel.yaml
data = [1, 3]
data.append(data)
print ruamel.yaml.dump(data)
会给你YAML一个锚(&id001
)和一个引用(*id001
):
&id001
- 1
- 3
- *id001
你的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的增强版本。