python - 在配置文件中使用字典而不是列表是一个坏习惯吗?
问题描述
考虑以下 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
我知道第二种表示在逻辑上是适合这种情况的一种,但我发现使用第一种表示更方便,以便能够迭代并直接获取键/对象名称。
所以,我的问题是:
在提供的示例中将列表表示为字典是否被认为是一种坏习惯,以便轻松访问项目的名称/键?
这样做有什么缺点或问题吗?
解决方案
什么是坏习惯,什么是合乎逻辑的,是有争议的。我认为您假设因为items
您的根级别映射中的键是复数,所以该值由多个项目组成并且应该是一个序列。我认为这不一定是真的。
但是,如果映射中作为值的键值对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'])
with 类通过提供和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
。然而,这似乎不像没有标签的版本那样用户友好,尽管在这种情况下显式比隐式更好。
假设以上是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 文档根级别的唯一键,那么当然根本不需要该键,那么您应该将标签放在文档的开头并有一个序列作为根节点。
推荐阅读
- javascript - xmlHttpRequest.responseText 问题(未定义)
- python - 使用 Tensorflow-2.0 tf.optimizers 时如何修复“给定对象不是优化器实例”?
- javascript - 用 lodash 对对象数组进行排序:不工作
- php - Laravel:如何防止像 created_at user_id_created 这样的值发送到前端
- html - 使用 css 选择器对齐图像
- angular - 延迟加载模块的子路由在角度元素中不起作用
- java - Invocation.Builder java如何将json作为字符串而不是实体发布
- vuejs2 - 使用计算属性动态设置表单操作
- mysql - 指定 LIKE 子句可以查看的 WHERE
- r - 使用 R 将一列中的值添加到另一列中缺少第二列中的值