考虑以下yaml配置文件:
items:
item_A:
field_A: some_value
field_B: some_other_value
item_B:
field_A: some_value
field_B: some_other_value
表示此问题的逻辑方法是在每个项目前面添加破折号,使其成为项目列表:
items:
- item_A:
field_A: some_value
field_B: some_other_value
- item_B:
field_A: some_value
field_B: some_other_value
我想轻松访问对象的名称(item_A等)。
遍历以前的配置时,
for item in items:
print(item) # here, 'item' will be the keys in the items dict (eg. 'item_A')
相对于后者
for item in items:
print(item) # here, 'item' will be a full dict (eg. "item_A":{"field_A":"some_value"..)
# if I want access to the name item_A, I need to do item.keys()[0]- not so friendly
我知道第二种表示形式在逻辑上是正确的,但是我发现使用第一种表示形式更方便,以便能够迭代并直接获得键/对象名称。
所以,我的问题是:
是否像在所提供的示例中那样将列表表示为字典被认为是一种坏习惯,以便轻松访问商品的名称/关键字?
这样做有什么弊端或问题吗?
答案 0 :(得分:1)
什么是坏习惯,还有什么逻辑是值得商bat的。我认为
您假设由于根级别映射中的密钥items
是
复数,该值包含多个项目,应为
顺序。我认为这不一定是正确的。
但是,如果键值在映射中的顺序为value
为items
(即具有键item_A
和item_B
的键)
比您必须使用列表更重要,您可能想要做:
items:
- name: item_A
field_A: some_value
field_B: some_other_value
- name: item_B
field_A: some_value
field_B: some_other_value
将其加载到变量data
中时,就不再像以前那样容易访问item_B
与您的解决方案。加载后可以执行的操作是:
data['items'] = Items(data['items'])
具有类Items
的适当地提供对基础的访问
通过提供__getitem__
和__iter__
的数据结构,以便您可以做到
items = data['items']
for item_name in items:
item = items[item_name]
通过使用标签,您可以在加载后无需后处理步骤的情况下完成操作
items: !Items
- name: item_A
field_A: some_value_1
field_B: some_other_value_1
- name: item_B
field_A: some_value_2
field_B: some_other_value_2
并注册您的课程Items
。但是,这似乎不像
没有标签的版本,尽管在这种情况下,IMO比隐含的要好得多。
假设以上为input.yaml
:
import sys
from pathlib import Path
import ruamel.yaml
input = Path('input.yaml')
yaml = ruamel.yaml.YAML()
@yaml.register_class
class Items:
def __init__(self, items):
self.item_list = items
@classmethod
def from_yaml(cls, constructor, node):
return cls(constructor.construct_sequence(node, deep=True))
def __getitem__(self, key):
if isinstance(key, int):
return self.item_list[key]
for item in self.item_list:
if item['name'] == key:
return item
def __iter__(self):
for item in self.item_list:
yield item['name']
data = yaml.load(input)
items = data['items']
print('item1', items[1]['field_A'])
print('item2', items['item_A']['field_A'])
for item_name in items:
item = items[item_name]
print('item3', item['field_B'])
给出:
item1 some_value_2
item2 some_value_1
item3 some_other_value_1
item3 some_other_value_2
如果items
是YAML文档根级的唯一密钥,
那么当然完全不需要该键,那么您
应该将标签放在文档的开头,并在其中添加一个
序列作为根节点。