在YAML中不能真正替換字符串值,如用另一個子字符串'替換某個字符串的子字符串'。然而YAML確實有可能標記的節點(在你的情況下,列表[「A」,「B」,「C」]與anchor和再利用,作爲一個alias node。
錨採取的形式&some_id
和是在節點和別名之前插入的節點由*some_id
(而不是節點)指定
這與字符串級別的替換不同,因爲在分析YAML文件時可以保留引用。在Python中針對集合類型上的任何錨加載YAML的情況(即當在標量上使用錨時,即而不是):
import sys
import ruamel.yaml as yaml
yaml_str = """\
sub: &sub0 [a, b, c]
command:
params:
cmd1:
type: string
# Get the list defined in 'sub'
enum : *sub0
description: Exclude commands from the test list.
cmd2:
type: string
# Get the list defined in 'sub'
enum: *sub0
"""
data1 = yaml.load(yaml_str, Loader=yaml.RoundTripLoader)
# the loaded elements point to the same list
assert data1['sub'] is data1['command']['params']['cmd1']['enum']
# change in cmd2
data1['command']['params']['cmd2']['enum'][3] = 'X'
yaml.dump(data1, sys.stdout, Dumper=yaml.RoundTripDumper, indent=4)
這將輸出:
sub: &sub0 [a, X, c]
command:
params:
cmd1:
type: string
# Get the list defined in 'sub'
enum: *sub0
description: Exclude commands from the test list.
cmd2:
type: string
# Get the list defined in 'sub'
enum: *sub0
請注意,原來的錨名在ruamel.yamlpreserved²。
如果你不想在你的輸出的錨和別名,你可以覆蓋RoundTripRepresenter
子類的RoundTripDumper
的ignore_aliases
方法(該方法有兩個參數,但使用lambda *args: ....
你不必知道這個問題):
dumper = yaml.RoundTripDumper
dumper.ignore_aliases = lambda *args : True
yaml.dump(data1, sys.stdout, Dumper=dumper, indent=4)
其中給出:
sub: [a, X, c]
command:
params:
cmd1:
type: string
# Get the list defined in 'sub'
enum: [a, X, c]
description: Exclude commands from the test list.
cmd2:
type: string
# Get the list defined in 'sub'
enum: [a, X, c]
這一招可以用在YAML文件讀取,如果你做了字符串替換,通過重新閱讀而忽略了你傾倒的材料別名:
data2 = yaml.load(yaml.dump(yaml.load(yaml_str, Loader=yaml.RoundTripLoader),
Dumper=dumper, indent=4), Loader=yaml.RoundTripLoader)
# these are lists with the same value
assert data2['sub'] == data2['command']['params']['cmd1']['enum']
# but the loaded elements do not point to the same list
assert data2['sub'] is not data2['command']['params']['cmd1']['enum']
data2['command']['params']['cmd2']['enum'][5] = 'X'
yaml.dump(data2, sys.stdout, Dumper=yaml.RoundTripDumper, indent=4)
現在只有一個'b'
改爲'X'
:
sub: [a, b, c]
command:
params:
cmd1:
type: string
# Get the list defined in 'sub'
enum: [a, b, c]
description: Exclude commands from the test list.
cmd2:
type: string
# Get the list defined in 'sub'
enum: [a, X, c]
如圖所示上方集合類型使用錨/別名時,這僅僅是必須的,而不是當你使用它的標。
¹由於YAML可以創建對象,然而,有可能影響 如果創建這些對象的解析器。 This answer描述瞭如何做到這一點。
²保留名原是不可用,但在ruamel.yaml的更新被實施
看一看:http://en.wikipedia.org/wiki/YAML#References – smj
我改變了你YAML代碼,因爲它在序列「sub」中的'b'之後錯過了一個單引號。請注意,這些引用是多餘的,在我的回答中使用輸入時,我將它們排除在外。 – Anthon