我的程序包含许多配置参数,所以我正在寻找一种方法,将它们都放在一个位置,可以从项目中的每个文件访问. 我想到了一个配置模块,它将充当到包含配置参数的YAML文件的接口.我想要的一个要求是能够使用属性(点)表示法访问配置对象.我找到了AttrDict库,并编写了以下代码:

import yaml
from attrdict import AttrDict


def get_cfg():
    return cfg_node


def dump(out_filepath):
    with open(out_filepath, 'w') as file:
        yaml.dump(attrdict_to_dict(cfg_node), file)


def load_yaml(filepath):
    global cfg_node
    with open(filepath, 'r') as file:
        cfg_node = dict_to_attrdict(yaml.safe_load(file))


def attrdict_to_dict(myAttrdict):
    dictionary = dict(myAttrdict)
    for k in myAttrdict:
        value = dictionary[k]
        if isinstance(value, AttrDict):
            dictionary[k] = attrdict_to_dict(value)
    return dictionary


def dict_to_attrdict(dictionary):
    myAttrdict = AttrDict()
    for k in dictionary:
        value = dictionary[k]
        if isinstance(value, dict):
            myAttrdict.__setattr__(k, attrdict_to_dict(value))
    return myAttrdict


cfg_node = AttrDict()
cfg_node.b = "value_b"
cfg_node.a = AttrDict()
cfg_node.a.b = AttrDict()
cfg_node.a.c = "nested_c"
cfg_node.a.b.e= "double_nested_e"

问题是这个库不允许嵌套的AttrDict().

print(cfg_node)
 >>> {'b': 'value_b', 'a': AttrDict({})}

但是,如果我执行以下操作,嵌套赋值可以工作,但我被迫显式使用嵌套对象,这对我的目的没有用处:

cfg_node = AttrDict()
cfg_node.b = "value_b"
a =  AttrDict()
a.c = "nested_value_c"
cfg_node.a = a
print(cfg_node)
 >>> {'b': 'value_b', 'a': AttrDict({'c':'nested_value_c'})}

推荐答案

我已经查阅了AttrDict的文档,恐怕递归属性访问是不可能的.请看这里:

递归属性访问会产生浅层副本,因此是递归的 赋值将失败(因为您将写入该 词典):

> attr = AttrDict('foo': {})
> attr.foo.bar = 'baz'
> attr.foo
{}

他们建议用AttrMap来代替.然而,我已经try 使用它,并且从导入中得到了正确的错误.我将会调查此事.*更新如下

目前,您可以做的是定义您的定制AttrDict.

class AttrDict(dict):

    def __init__(self, *args, **kwargs):
        super(AttrDict, self).__init__(*args, **kwargs)
        self.__dict__ = self


if __name__ == '__main__':
    cfg_node = AttrDict()
    cfg_node.b = "value_b"
    cfg_node.a = AttrDict()
    cfg_node.a.b = AttrDict()
    cfg_node.a.c = "nested_c"
    cfg_node.a.b.e = "double_nested_e"
    print(cfg_node)
    print(cfg_node.a.b.e)

根据您的需要,这里的输出是:

{'b': 'value_b', 'a': {'b': {'e': 'double_nested_e'}, 'c': 'nested_c'}}
double_nested_e

如果您使用的是IDE,当您访问AttrDict的键时,您还将获得代码完成.

另请参阅here,您可以向自定义类添加其他方法来增强其功能.

希望这个能帮上忙!

Update在AttrMap库上.我问过它here,我使用的是python3.8,但库中包含list[str],这只在python3.9上可用.

Python相关问答推荐

线性模型PanelOLS和statmodels OLS之间的区别

比较两个数据帧并并排附加结果(获取性能警告)

SQLGory-file包FilField不允许提供自定义文件名,自动将文件保存为未命名

ModuleNotFound错误:没有名为Crypto Windows 11、Python 3.11.6的模块

非常奇怪:tzLocal.get_Localzone()基于python3别名的不同输出?

沿着数组中的轴计算真实条目

通过pandas向每个非空单元格添加子字符串

从一个系列创建一个Dataframe,特别是如何重命名其中的列(例如:使用NAs/NaN)

在单个对象中解析多个Python数据帧

如何检测鼠标/键盘的空闲时间,而不是其他输入设备?

如何创建引用列表并分配值的Systemrame列

Discord.py -

如何过滤组s最大和最小行使用`transform`'

如何将相同组的值添加到嵌套的Pandas Maprame的倒数第二个索引级别

有没有办法在不先将文件写入内存的情况下做到这一点?

Django.core.exceptions.SynchronousOnlyOperation您不能从异步上下文中调用它-请使用线程或SYNC_TO_ASYNC

在matplotlib中重叠极 map 以创建径向龙卷风图

如何在Quarto中的标题页之前创建序言页

时间戳上的SOAP头签名无效

基于2级列表的Pandas 切片3级多索引