Load YAML as nested objects instead of dictionary in Python

前端 未结 3 777
没有蜡笔的小新
没有蜡笔的小新 2020-12-07 04:09

I have a configuration file in YAML that is currently loaded as a dictionary using yaml.safe_load. For convenience in writing my code, I\'d prefer to load it as a set of nes

3条回答
  •  南方客
    南方客 (楼主)
    2020-12-07 04:22

    If you annotate the root node of the YAML file with a tag, you can define Python classes deriving from YAMLObject to deal with this as described in the PyYAML documentation.

    However, if you prefer your YAML to stay clean from tags, you can construct the nested classes yourself (taken from my answer to a similar question):

    import yaml
    
    class BItem:
        def __init__(self, q, r, s):
            self.q, self.r, self.s = q, r, s
    
    class CItem:
        def __init__(self, raw):
            self.d, self.e, self.f = raw['d'], raw['e'], raw['f']
    
    class Root:
        def __init__(self, raw):
            self.a = raw['a']
            self.b = [BItem(i['q'], i['r'], i['s']) for i in raw['b']]
            self.c = CItem(raw['c'])
    
    mydict = Root(yaml.safe_load("""
    a: 1
    b:
    - q: "foo"
      r: 99
      s: 98
    - q: "bar"
      r: 97
      s: 96
    c:
      d: 7
      e: 8
      f: [9,10,11]
    """))
    

    However, this approach only works if your YAML is structured homogeneously. You gave a heterogeneous structure by having differently named fields in the list of b (q, r, s in the first item; x, y, z in the second item). I changed the YAML input to have the same field names because with different fields, this approach does not work. I am unsure whether your YAML is actually heterogeneous or you just accidentally made it so for an example. If your YAML actually is heterogeneous, accessing the items via dict access is the only viable way since then, the keys in the YAML file do not correspond to class fields; they are dynamic mapping entries.

提交回复
热议问题