YAML别名更改值

时间:2018-10-30 04:48:09

标签: python yaml

a = '''
test: &test
    a: 1
    b: 2
test1:
    <<: *test
    a: 2
'''
dict = yaml.load(a)
dict['test']['a'] = 3
dict['test']['b'] = 4
print dict

此打印{'test': {'a': 3, 'b': 4}, 'test1': {'a': 2, 'b': 2}}

但是我想打印{'test': {'a': 3, 'b': 4}, 'test1': {'a': 3, 'b': 4}}

更改dict['test1']时如何更改dict['test']的值?

2 个答案:

答案 0 :(得分:0)

当您使用合并键操作<<: *ref时,如果键尚不存在,则yaml加载程序将创建一个dict,然后仅从引用的dict中复制项目。然后更改为随后引用的dict不会更改新的dict。无法解决这个问题。

直接引用不会创建副本。例如:

a = '''
test: &test
    a: 1
    b: 2
test1: *test
'''
dict = yaml.load(a)
dict['test']['a'] = 3
dict['test']['b'] = 4
print(dict)

{'test': {'a': 3, 'b': 4}, 'test1': {'a': 3, 'b': 4}}

答案 1 :(得分:0)

当合并的步骤在负载的组成步骤中得到解决时,此操作将无效。

映射的实际键值对,即 test插入到映射的键值对中,即 test1的值,但前提是该值尚不存在(来自 test1映射本身或任何先前合并(如果列表为 指定)

因此a下的test1甚至从未获得值1,更不用说值3

您可以做的是将b的新值合并到您的test1中:

from __future__ import print_function

import sys
from ruamel.yaml import YAML
from ruamel.yaml.compat import StringIO

yaml = YAML()
yaml.indent(mapping=4)

a = """\
test: &ta
    a: 1
    b: 2
test1:
    <<: *ta
    a: 2
"""

data = yaml.load(a)
data['test']['a'] = 3
data['test']['b'] = 4

buf = StringIO()
yaml.dump(data, buf)

yaml2 = YAML(typ='safe')
print(yaml2.load(buf.getvalue()))

给出:

{'test': {'a': 3, 'b': 4}, 'test1': {'a': 2, 'b': 4}}

重要:

  • 屏蔽Python内置函数不是一个好主意,因此请勿使用dict作为变量名
  • 习惯上将"""用于多行字符串,并确保逃脱 如果您不希望文件以空行开头,请在第一行使用换行符
  • Python 2.7将于2020年寿终正寝。即使您必须使用它,也要习惯于 使用print()函数而不是print语句:使用 在您的python2代码的全部from __future__行。
  • 不要通过使用相同的字符串作为键和 锚点。对于您的示例,如果您引用test,则无法 在没有上下文的情况下知道您是一个人还是另一个人。