dict.py 3.05 KB
Newer Older
BO ZHANG's avatar
BO ZHANG committed
1
2
3
4
5
6
7
8
9
10
11
class DotDict(dict):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # 递归转换嵌套字典为 DotDict
        for key, value in self.items():
            if isinstance(value, dict) and not isinstance(value, DotDict):
                self[key] = DotDict(value)

    def __getattr__(self, key):
        """属性访问优先级:1. 内置属性 → 2. 键值 → 3. 报错"""
        try:
BO ZHANG's avatar
BO ZHANG committed
12
            # 优先返回内置属性(如 basis_keys, items 等方法)
BO ZHANG's avatar
BO ZHANG committed
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
            return object.__getattribute__(self, key)
        except AttributeError:
            if key in self:
                # 其次返回键值(若存在)
                return self[key]
            # 属性不存在时抛出标准异常
            raise AttributeError(
                f"'{type(self).__name__}' object has no attribute '{key}'"
            )

    def __setattr__(self, key, value):
        """属性设置规则:下划线开头为内置属性,否则为键值"""
        if key.startswith("_"):
            # 内置属性直接存储(如 _internal_var)
            object.__setattr__(self, key, value)
        else:
            # 键值处理:自动转换嵌套结构
            if isinstance(value, dict) and not isinstance(value, DotDict):
                value = DotDict(value)
            self[key] = value  # 存储为字典键值

    def __delattr__(self, key):
        """删除逻辑:区分内置属性和键值"""
        if key.startswith("_"):
            object.__delattr__(self, key)
        else:
            if key in self:
                del self[key]
            else:
                raise AttributeError(
                    f"'{type(self).__name__}' object has no attribute '{key}'"
                )


# dd = DotDict({"a": {"b": {"c": 1}}})


class CaseInsensitiveDict(dict):
    def __init__(self, *args, **kwargs):
        self._key_map = {}
        super().__init__(*args, **kwargs)
        # 初始化时处理传入的键
        for key in list(self.keys()):
            self._key_map[key.lower()] = key

    def __setitem__(self, key, value):
        key_lower = key.lower() if isinstance(key, str) else key
        self._key_map[key_lower] = key  # 记录原始键
        super().__setitem__(key_lower, value)

    def __getitem__(self, key):
        key_lower = key.lower() if isinstance(key, str) else key
        return super().__getitem__(key_lower)

    def __delitem__(self, key):
        key_lower = key.lower() if isinstance(key, str) else key
        del self._key_map[key_lower]
        super().__delitem__(key_lower)

    def __contains__(self, key):
        key_lower = key.lower() if isinstance(key, str) else key
        return super().__contains__(key_lower)

    def get(self, key, default=None):
        key_lower = key.lower() if isinstance(key, str) else key
        return super().get(key_lower, default)

    def keys(self):
        return self._key_map.values()  # 返回原始键

    def items(self):
        for key_lower, value in super().items():
            yield self._key_map.get(key_lower, key_lower), value