在YAML中,您可以具有锚点和别名。这样,您可以直接或间接地建立自我引用的结构。
如果YAML没有这种自我引用的可能性,则可以先构造所有子代,然后一次性创建父代结构。但是由于自身的引用,您可能还没有孩子来“填写”正在创建的结构。通过使用生成器的两步过程(我将其称为“两步”,因为它在方法结束之前只有一个屈服),您可以部分创建一个对象,并使用自引用填充它,因为对象存在(即定义了它在内存中的位置)。
好处不是速度,而是纯粹因为使自引用成为可能。
如果您只是从答案中简化示例,则会加载以下内容:
import sysimport ruamel.yaml as yamlclass Foo(object): def __init__(self, s, l=None, d=None): self.s = s self.l1, self.l2 = l self.d = ddef foo_constructor(loader, node): instance = Foo.__new__(Foo) yield instance state = loader.construct_mapping(node, deep=True) instance.__init__(**state)yaml.add_constructor(u'!Foo', foo_constructor)x = yaml.load('''&fooref!Foos: *foorefl: [1, 2]d: {try: this}''', Loader=yaml.Loader)yaml.dump(x, sys.stdout)但是如果您更改
foo_constructor()为:
def foo_constructor(loader, node): instance = Foo.__new__(Foo) state = loader.construct_mapping(node, deep=True) instance.__init__(**state) return instance
(删除收益,添加最终收益),您将获得
ConstructorError带有消息的:
found unconstructable recursive node in "<unipre string>", line 2, column 1: &fooref
PyYAML应该给出类似的消息。检查该错误的回溯,您可以看到ruamel.yaml / PyYAML在源代码中尝试解析别名的位置。



