我使用自定义YAML标记将YAML文件反序列化为Python对象。像这样:
MyList:
Object1: !MyObject
value1: Test
value2: 1.0
通过class_method
from_yaml
我调用MyObject
__init__
方法,并将loader.construct_mapping
提供的所有字段发送给它。
@classmethod
def from_yaml(cls, loader, node):
fields = loader.construct_mapping(node, deep = True)
return cls(**fields)
所有已配置的字段都以__init__
MyObject
方式传递给MyObject
。全部,但只有一个:所描述的Object1
实例的实际名称,即字符串name == "Object1"
。
如何获取实例的名称以便执行def __init__(self, name, **fields):
self.name = name
for attr in fields:
val = fields[attr]
setattr(self, attr, val)
scale
答案 0 :(得分:0)
您的YAML中有一个键Object1
和一个带有标记!MyObject
的标记映射的值。对于YAML,该键不是实例的名称,它只是映射中的一个键,其值恰好是标记映射。
构建标记的映射该密钥不可用时,因为它不是您对象的一部分。解析器当然已经将那个键Object1
构建在某个节点作为节点,当它开始解析你的对象时,但是你不能在不大量改变解析器的情况下访问它。如果你这样做,如果你的YAML看起来像事情可能会破坏:
MyList:
- !MyObject
value1: Test
value2: 1.0
没有这样的钥匙。
IMO你应该改变你的YAML看起来像:
MyList: !MyObject
Object1:
value1: Test
value2: 1.0
或者对于以下内容,这更容易加载:
MyList:
- !MyObject
name: Object1
value1: Test
value2: 1.0
如果您无法更改YAML,最好的选择是编写一个(递归)树木漫步者,在您致电safe_load()
后更新您的对象。
您还应该考虑将from_yaml
写为生成器。就像现在一样,只要你的!MyObject
获得更复杂的值,可能会在未来某个时候包含自我引用,就会中断。