【发布时间】:2017-06-13 12:53:16
【问题描述】:
我一直在阅读 PyYAML 源代码,试图了解如何定义一个合适的构造函数,我可以使用 add_constructor 添加该构造函数。我现在对该代码的工作原理有了很好的理解,但我仍然不明白为什么 SafeConstructor 中的默认 YAML 构造函数是生成器。比如SafeConstructor的方法construct_yaml_map:
def construct_yaml_map(self, node):
data = {}
yield data
value = self.construct_mapping(node)
data.update(value)
我了解生成器如何在BaseConstructor.construct_object 中使用,如下所示以存根一个对象,并且仅在将deep=False 传递给construct_mapping 时才使用来自节点的数据填充它:
if isinstance(data, types.GeneratorType):
generator = data
data = generator.next()
if self.deep_construct:
for dummy in generator:
pass
else:
self.state_generators.append(generator)
并且我了解在deep=False 为construct_mapping 的情况下,BaseConstructor.construct_document 中的数据是如何生成的。
def construct_document(self, node):
data = self.construct_object(node)
while self.state_generators:
state_generators = self.state_generators
self.state_generators = []
for generator in state_generators:
for dummy in generator:
pass
我不明白的是,将数据对象存根并通过迭代 construct_document 中的生成器来处理对象的好处。是否必须这样做以支持 YAML 规范中的某些内容,还是提供性能优势?
This answer on another question 有点帮助,但我不明白为什么这个答案会这样:
def foo_constructor(loader, node):
instance = Foo.__new__(Foo)
yield instance
state = loader.construct_mapping(node, deep=True)
instance.__init__(**state)
而不是这个:
def foo_constructor(loader, node):
state = loader.construct_mapping(node, deep=True)
return Foo(**state)
我已经测试过后一种形式适用于发布在另一个答案上的示例,但也许我错过了一些极端情况。
我使用的是 3.10 版的 PyYAML,但看起来有问题的代码与最新版 (3.12) 的 PyYAML 中的代码相同。
【问题讨论】:
标签: python yaml pyyaml ruamel.yaml