序列的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中的所有元素,但您正在使用合并键将它们合

考虑以下文件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
中的所有元素,但您正在使用合并键将它们合并,因为@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