ตัวอย่างของคุณไม่ถูกต้องเป็นเพียงเพราะคุณเลือกตัวละครที่สงวนไว้เพื่อเริ่มสเกลาร์ด้วย หากคุณแทนที่*
ด้วยอักขระที่ไม่ได้จองไว้อื่น ๆ (ฉันมักจะใช้อักขระที่ไม่ใช่ ASCII สำหรับสิ่งนั้นเนื่องจากไม่ค่อยมีการใช้เป็นส่วนหนึ่งของข้อกำหนดบางอย่าง) คุณจะได้รับ YAML ตามกฎหมายอย่างสมบูรณ์:
paths:
root: /path/to/root/
patha: ♦root♦ + a
pathb: ♦root♦ + b
pathc: ♦root♦ + c
สิ่งนี้จะโหลดเข้าสู่การเป็นตัวแทนมาตรฐานสำหรับการแมปในภาษาที่ parser ของคุณใช้และไม่ขยายอะไรอย่างน่าอัศจรรย์
ในการทำเช่นนั้นให้ใช้ประเภทวัตถุเริ่มต้นในเครื่องเช่นเดียวกับในโปรแกรม Python ต่อไปนี้:
# coding: utf-8
from __future__ import print_function
import ruamel.yaml as yaml
class Paths:
def __init__(self):
self.d = {}
def __repr__(self):
return repr(self.d).replace('ordereddict', 'Paths')
@staticmethod
def __yaml_in__(loader, data):
result = Paths()
loader.construct_mapping(data, result.d)
return result
@staticmethod
def __yaml_out__(dumper, self):
return dumper.represent_mapping('!Paths', self.d)
def __getitem__(self, key):
res = self.d[key]
return self.expand(res)
def expand(self, res):
try:
before, rest = res.split(u'♦', 1)
kw, rest = rest.split(u'♦ +', 1)
rest = rest.lstrip() # strip any spaces after "+"
# the lookup will throw the correct keyerror if kw is not found
# recursive call expand() on the tail if there are multiple
# parts to replace
return before + self.d[kw] + self.expand(rest)
except ValueError:
return res
yaml_str = """\
paths: !Paths
root: /path/to/root/
patha: ♦root♦ + a
pathb: ♦root♦ + b
pathc: ♦root♦ + c
"""
loader = yaml.RoundTripLoader
loader.add_constructor('!Paths', Paths.__yaml_in__)
paths = yaml.load(yaml_str, Loader=yaml.RoundTripLoader)['paths']
for k in ['root', 'pathc']:
print(u'{} -> {}'.format(k, paths[k]))
ซึ่งจะพิมพ์:
root -> /path/to/root/
pathc -> /path/to/root/c
การขยายจะทำได้ทันทีและจัดการกับคำจำกัดความซ้อนกัน แต่คุณต้องระวังเกี่ยวกับการไม่เรียกใช้การเรียกซ้ำแบบไม่สิ้นสุด
ด้วยการระบุดัมเปอร์คุณสามารถดัมพ์ YAML ดั้งเดิมจากข้อมูลที่โหลดได้เนื่องจากการขยายแบบ on-the-fly:
dumper = yaml.RoundTripDumper
dumper.add_representer(Paths, Paths.__yaml_out__)
print(yaml.dump(paths, Dumper=dumper, allow_unicode=True))
สิ่งนี้จะเปลี่ยนการจัดลำดับคีย์การแมป ถ้าเป็นปัญหาที่คุณต้องให้(นำเข้าจาก)self.d
CommentedMap
ruamel.yaml.comments.py