PyYaml:无法从构造函数类的 __init__ 方法中访问嵌套的实例属性

穆克斯沃拉

我正在尝试使用 PyYamladd_constructor()函数从 YAML 节点返回一个类实例。

构造器类:

class PrintAttributes():
    
    def __init__(self, a, b):
        self._a = a
        self.b = b
        print(f"instance a => attr: {self._a}, arg: {a}")
        print(f"instance b => attr: {self.b}, arg: {b}")
    
    def __repr__(self):
        return "%s(a=%r, b=%r)" % (self.__class__.__name__, self._a, self.b)

手动实例化时,这似乎按预期工作:

>>> PrintAttributes(3,4)

instance a => attr: 3, arg: 3
instance b => attr: 4, arg: 4

PrintAttributes(a=3, b=4)

这是我将使用的两个 YAML 文件:

simple_yaml = """
a: 3
b: 4
"""

nested_yaml = """
a: 
  value: 3
b:
  value: 4
"""

这表明我可以使用yaml.load()方法正确加载它们

io_simple = io.StringIO(simple_yaml)
io_nested = io.StringIO(nested_yaml)
>>> d_simple = yaml.load(io_simple, Loader=yaml.SafeLoader)
>>> print(d_simple)
{'a': 3, 'b': 4}

>>> d_nested = yaml.load(io_nested, Loader=yaml.SafeLoader)
>>> print(d_nested)
{'a': {'value': 3}, 'b': {'value': 4}}

再一次,如果我将上述字典传递给类构造函数,它可以正常工作:

>>> print(PrintAttributes(**d_simple))
instance a => attr: 3, arg: 3
instance b => attr: 4, arg: 4
PrintAttributes(a=3, b=4)

>>> print(PrintAttributes(**d_nested))
instance a => attr: {'value': 3}, arg: {'value': 3}
instance b => attr: {'value': 4}, arg: {'value': 4}
PrintAttributes(a={'value': 3}, b={'value': 4})

现在,让我们创建用于定义自定义“构造函数”的辅助函数,并将加载的 YAML 映射到自定义类PrintAttributes

def PrintAttributes_constructor(loader: yaml.SafeLoader, node: yaml.nodes.MappingNode) -> PrintAttributes:
    """Construct a PrintAttributes dictionary"""
    return PrintAttributes(**loader.construct_mapping(node))
    
def get_loader():
    """Add constructors to PyYAML loader."""
    loader = yaml.SafeLoader
    loader.add_constructor('!PrintAttributes', PrintAttributes_constructor)
    return loader

这些是上面带有!PrintAttributes用于调用构造函数的附加标记的 YAML 文件

simple_yaml_construct = """
tag_here: !PrintAttributes
 a: 3
 b: 4
"""

nested_yaml_construct = """
tag_here: !PrintAttributes
  a: 
    value: 3
  b:
    value: 4
"""

当我使用简单(即非嵌套)YAML 文件时,这可以正常工作:

>>> print(yaml.load(io_simple_construct, Loader=get_loader()))
instance a => attr: 3, arg: 3
instance b => attr: 4, arg: 4
{'tag_here': PrintAttributes(a=3, b=4)}

虽然,当我尝试加载/解析嵌套的 YAML 文件时,我无法在实例初始化期间访问参数:

>>> print(yaml.load(io_nested_construct, Loader=get_loader()))
instance a => attr: {}, arg: {}
instance b => attr: {}, arg: {}
{'tag_here': PrintAttributes(a={'value': 3}, b={'value': 4})}

我的目标是在实例初始化期间访问这些值以更新类变量。我可以使用第一个 YAML 文件执行此操作,但无法访问第二个 YAML 文件的嵌套值。

虽然,我确实在实例的表示中看到了嵌套值(即__repr__())。所以,他们肯定是满载的。

另一件要注意的事情是__repr__()PrintAttributes更改返回的类名tag_here

我错过了什么,还是只是一些PyYAML限制?

谢谢

飞翔

您需要附加参数deep=True

    return PrintAttributes(**loader.construct_mapping(node, deep=True))

如果没有这个,子字典ab稍后会在您的构造函数返回后填充。这就是为什么它们在 中包含空值__init__,但在构造完成后包含正确值。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章