万能的字典,可以通过 config.server.port 的方式访问,也可以通过get_config("server.port")的方式访问,还可以config['server']['port']访问值

万能的字典,可以通过 config.server.port 的方式访问,也可以通过get_config("server.port")的方式访问,还可以config['server']['port']访问值

class DotDict(dict):
    """
    一个字典类,支持通过点分路径访问和设置嵌套的字典值。
    """

    def __init__(self, *args, **kwargs):
        """
        初始化DotDict实例,自动将嵌套的字典转换为DotDict实例。
        """
        super().__init__(*args, **kwargs)
        self._convert_to_dotdict()

    def _convert_to_dotdict(self):
        """
        递归地将字典值转换为DotDict实例。
        """
        for key, value in self.items():
            if isinstance(value, dict):
                self[key] = DotDict(value)

    def __getattr__(self, item):
        """
        允许使用属性访问语法来获取字典值。
        如果属性不存在,抛出AttributeError异常。
        """
        try:
            return self.get_config(item)
        except KeyError:
            raise AttributeError(f"{self.__class__.__name__} object has no attribute '{item}'")

    def __setattr__(self, key, value):
        """
        允许使用属性赋值语法来设置字典值。
        如果键不存在,将创建新的键值对。
        """
        self.set_config(key, value)


    def get_config_default(self, path, default=None):
        """
        通过点分路径获取配置值,找不到就返回默认值

        :param path: 配置项的点分路径。
        :param default: 默认值 None
        :return: 配置值。
        """
        keys = path.split('.')
        value = self
        for key in keys:
            if isinstance(value, dict) and key in value:
                value = value[key]
            else:
                return default
        return value


    def get_config(self, path):
        """
        通过点分路径获取配置值。

        :param path: 配置项的点分路径。
        :return: 配置值。
        """
        keys = path.split('.')
        value = self
        for key in keys:
            if isinstance(value, dict) and key in value:
                value = value[key]
            else:
                raise KeyError(f"Key '{key}' not found in path '{path}'")
        return value

    def set_config(self, path, value):
        """
        通过点分路径设置配置值。

        :param path: 配置项的点分路径。
        :param value: 要设置的值。
        """
        keys = path.split('.')
        target = self
        for key in keys[:-1]:
            if key not in target or not isinstance(target[key], dict):
                target[key] = DotDict()
            target = target[key]
        target[keys[-1]] = value

测试代码

from core.common.libs.dot_dict import DotDict

configs = {
    "server": {
        "port": 8080,
        "host": "localhost"
    },
    "database": {
        "user": "admin",
        "password": "secret",
        "host": "localhost",
    }
}

# 创建DotDict实例
dot_config = DotDict(configs)

# 使用get_config方法
port = dot_config.get_config("server.port")
password = dot_config.get_config("database.password")
print(port)
print(password)
# 使用set_config方法
dot_config.set_config("server.host", "127.0.0.1")
# 使用 . 出对象的方式获取
print(dot_config.server.host)
# 使用 . 出对象的方式赋值
dot_config.server.path = "/image"
print(dot_config.server.path)
print(dot_config.get_config("server.path"))
# 使用字典的方式获取
print(dot_config['server']['host'])
print(dot_config['server']['port'])
print(dot_config.get_config("server.host"))
# 使用字典的方式赋值
dot_config['server']['aaa'] = "5000"
print(dot_config.server.aaa)
print(dot_config.get_config("server.aaa"))


最后输出

posted @ 2024-06-15 23:23  Excel2016  阅读(24)  评论(0)    收藏  举报