我正在尝试使用 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))
如果没有这个,子字典a
和b
稍后会在您的构造函数返回后填充。这就是为什么它们在 中包含空值__init__
,但在构造完成后包含正确值。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句