序列的YAML锚?
考虑以下文件YAML文件:序列的YAML锚?,yaml,pyyaml,ruamel.yaml,Yaml,Pyyaml,Ruamel.yaml,考虑以下文件YAML文件: A: &B - x: 1 y: 2 - x: 10 y: 20 C: <<: *B 屈服: {'A': [{'x': 1, 'y': 2}, {'x': 10, 'y': 20}], 'C': {'x': 1, 'y': 2}} 可以看出,锚点B仅包括序列的第一个元素。为什么?我想要一个包含整个序列的锚,这样python字典中A和C的值是相同的。如何做到这一点?锚B包含A中的所有元素,但您正在使用合并键将它们合
A:
&B
- x: 1
y: 2
- x: 10
y: 20
C:
<<: *B
屈服:
{'A': [{'x': 1, 'y': 2}, {'x': 10, 'y': 20}], 'C': {'x': 1, 'y': 2}}
可以看出,锚点
B
仅包括序列的第一个元素。为什么?我想要一个包含整个序列的锚,这样python字典中A
和C
的值是相同的。如何做到这一点?锚B
包含A
中的所有元素,但您正在使用合并键将它们合并,因为@Hadyniak已经指出您使用的是错误的。因为别名*B
在
编写器步骤,在解释中的
0.17.2
,对于较旧版本,您需要复制和修改组合节点
方法:
import copy
yaml_str = """\
A:
&B
- x: 1
y: 2
- x: 10
y: 20
C:
*B
"""
class MyComposer(ruamel.yaml.composer.Composer):
def compose_node(self, parent, index):
# type: (Any, Any) -> Any
if self.parser.check_event(ruamel.yaml.events.AliasEvent):
event = self.parser.get_event()
alias = event.anchor
if alias not in self.anchors:
raise ComposerError(
None,
None,
'found undefined alias {alias!r}'.format(alias=alias),
event.start_mark,
)
return copy.deepcopy(self.anchors[alias])
event = self.parser.peek_event()
anchor = event.anchor
if anchor is not None: # have an anchor
if anchor in self.anchors:
ws = (
'\nfound duplicate anchor {!r}\nfirst occurrence {}\nsecond occurrence '
'{}'.format((anchor), self.anchors[anchor].start_mark, event.start_mark)
)
warnings.warn(ws, ruamel.yaml.error.ReusedAnchorWarning)
self.resolver.descend_resolver(parent, index)
if self.parser.check_event(ruamel.yaml.events.ScalarEvent):
node = self.compose_scalar_node(anchor)
elif self.parser.check_event(ruamel.yaml.events.SequenceStartEvent):
node = self.compose_sequence_node(anchor)
elif self.parser.check_event(ruamel.yaml.events.MappingStartEvent):
node = self.compose_mapping_node(anchor)
self.resolver.ascend_resolver()
return node
yaml = ruamel.yaml.YAML()
yaml.Composer = MyComposer
c = yaml.load(yaml_str)
print(c['A'] is c['C'], c['A'] == c['C'])
c['A'][0]['x'] = 42
print('x:', c['C'][0]['x'])
它还提供:
False True
x: 1
你所说的
A
和C
相同是什么意思?您希望它们是相同的字典实例(c['A']是c['c']
),还是只是键和值是相同的(c['A']==c['c'],而c['A']不是c['c']
)?这是一个有趣的观点。我的意图是它们应该是独立的词典。然而,在我的特定用例中,c
的任何部分一旦被读取就不应该被修改。因此,如果c[`A']
和c['c`]
是同一本词典,那就可以了。但是我很好奇如果这两个字典必须不同,我需要做什么。虽然分析是正确的,“C
将包含A
中的所有元素”有点误导。假设OP正在加载代码片段,c['A']
不仅包含与c['c']
相同的键值对,实际上它是同一个字典。因此,更改c['A']
也会影响c['c']
。是否有一种明显的方法来确保字典的不同?
{
"A": [
{
"y": 2,
"x": 1
},
{
"y": 20,
"x": 10
}
],
"C": [
{
"y": 2,
"x": 1
},
{
"y": 20,
"x": 10
}
]
}
A: &B
- x: 1
y: 2
- x: 10
new: 333
C:
<<: *B
{
"A": [
{
"y": 2,
"x": 1
},
{
"x": 10,
"new": 333
}
],
"C": {
"y": 2,
"x": 1,
"new": 333
}
}
import ruamel.yaml
yaml_str = """\
A:
&B
- x: 1
y: 2
- x: 10
y: 20
C:
*B
"""
yaml = ruamel.yaml.YAML()
c = yaml.load(yaml_str)
print(c['A'] is c['C'], c['A'] == c['C'])
c['A'][0]['x'] = 42
print('x:', c['C'][0]['x'])
True True
x: 42
import ruamel.yaml
yaml_str = """\
A:
- &B1
x: 1
y: 2
- &B2
x: 10
y: 20
C:
- <<: *B1
- <<: *B2
"""
yaml = ruamel.yaml.YAML()
c = yaml.load(yaml_str)
print(c['A'] is c['C'], c['A'] == c['C'])
c['A'][0]['x'] = 42
print('x:', c['C'][0]['x'])
False True
x: 1
import copy
yaml_str = """\
A:
&B
- x: 1
y: 2
- x: 10
y: 20
C:
*B
"""
yaml = ruamel.yaml.YAML()
yaml.composer.return_alias = lambda s: copy.deepcopy(s)
c = yaml.load(yaml_str)
print(c['A'] is c['C'], c['A'] == c['C'])
c['A'][0]['x'] = 42
print('x:', c['C'][0]['x'])
False True
x: 1
import copy
yaml_str = """\
A:
&B
- x: 1
y: 2
- x: 10
y: 20
C:
*B
"""
class MyComposer(ruamel.yaml.composer.Composer):
def compose_node(self, parent, index):
# type: (Any, Any) -> Any
if self.parser.check_event(ruamel.yaml.events.AliasEvent):
event = self.parser.get_event()
alias = event.anchor
if alias not in self.anchors:
raise ComposerError(
None,
None,
'found undefined alias {alias!r}'.format(alias=alias),
event.start_mark,
)
return copy.deepcopy(self.anchors[alias])
event = self.parser.peek_event()
anchor = event.anchor
if anchor is not None: # have an anchor
if anchor in self.anchors:
ws = (
'\nfound duplicate anchor {!r}\nfirst occurrence {}\nsecond occurrence '
'{}'.format((anchor), self.anchors[anchor].start_mark, event.start_mark)
)
warnings.warn(ws, ruamel.yaml.error.ReusedAnchorWarning)
self.resolver.descend_resolver(parent, index)
if self.parser.check_event(ruamel.yaml.events.ScalarEvent):
node = self.compose_scalar_node(anchor)
elif self.parser.check_event(ruamel.yaml.events.SequenceStartEvent):
node = self.compose_sequence_node(anchor)
elif self.parser.check_event(ruamel.yaml.events.MappingStartEvent):
node = self.compose_mapping_node(anchor)
self.resolver.ascend_resolver()
return node
yaml = ruamel.yaml.YAML()
yaml.Composer = MyComposer
c = yaml.load(yaml_str)
print(c['A'] is c['C'], c['A'] == c['C'])
c['A'][0]['x'] = 42
print('x:', c['C'][0]['x'])
False True
x: 1