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
12
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
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:
            # 优先返回内置属性(如 keys, items 等方法)
            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