您在文档中没有看到 deep=True 是因为您通常不需要将它用作 PyYAML 包的最终用户。
如果您跟踪 constructor.py 中使用 deep= 的方法的使用,您会来到 BaseConstructor() 类中的 construct_mapping() 和 construct_sequence(),并且这两个都调用 BaseConstructor.construct_object()。
该方法学习的相关代码为:
if tag_suffix is None:
data = constructor(self, node)
else:
data = constructor(self, tag_suffix, node)
if isinstance(data, types.GeneratorType):
generator = data
data = next(generator)
if self.deep_construct:
for dummy in generator:
pass
else:
self.state_generators.append(generator)
尤其是其中的for 循环,只有在传入deep=True 时才会执行。
Rougly 说如果来自构造函数的数据是生成器,那么它会遍历该数据(在for 循环中)直到生成器耗尽。使用该机制,那些构造函数可以包含yield 来创建基础对象,其详细信息可以在yield 之后填写。因为它们在这样的构造函数中只有一个yield,例如用于映射(构造为 Python dicts):
def construct_yaml_map(self, node):
data = {}
yield data
value = self.construct_mapping(node)
data.update(value)
我称之为两步过程(一步到yield,然后是方法的末尾。
在这样的两步构造函数中,要生成的data 被构造为空,生成然后填充。之所以如此,是因为您已经注意到了:递归。如果在下方某处有对data 的自引用,则data 在其所有子代都构建完成后无法构建,因为它必须等待自身构建完成。
deep 参数间接控制作为潜在生成器的对象是递归构建还是附加到列表self.state_generators 以供稍后解析。
然后,构建一个 YAML 文档归结为构建顶级对象并循环遍历 self.state_generators 中的潜在递归对象,直到没有剩下任何生成器(这个过程可能需要不止一次通过)。