如何让一个类同时支持 obj[‘key’] 和 obj.key 两种访问

10次阅读

要让类同时支持 obj[‘key’] 和 obj.key,需实现 getitem 和 __getattr__:前者处理方括号访问,后者在属性查找失败时兜底调用 self[key];注意避免与内置属性名冲突。

如何让一个类同时支持 obj[‘key’] 和 obj.key 两种访问

让一个类同时支持 obj['key']obj.key 两种访问方式,关键在于实现 python 的特殊方法:__getitem__ 支持方括号语法,__getattr__(或 __getattribute__)支持点号属性访问。

实现 __getitem__ 支持 obj['key']

只需在类中定义 __getitem__ 方法,让它根据传入的 key 查找并返回对应值。通常配合内部字典存储数据:

  • 把数据存在实例的字典(如 self._data = {})中
  • __getitem__ 中检查 key 是否存在,存在则返回值,否则可抛 KeyError

实现 __getattr__ 支持 obj.key

__getattr__ 只在属性常规查找失败时被调用(即该属性不在实例字典、类定义、父类中),适合做兜底处理:

  • __getattr__ 中尝试用 self[key](即调用已实现的 __getitem__)获取值
  • 若仍失败(比如 key 不存在),再抛 AttributeError,保持语义正确
  • 注意不要用 __getattribute__ 替代,它会在每次属性访问时触发,容易引发无限递归或性能问题

避免属性名和键名冲突

如果某个 key 恰好和内置属性(如 __len__)、方法名或你自定义的属性名重名,点号访问会优先走属性/方法,跳过 __getattr__

  • 例如 obj.keys 会返回字典的 keys() 方法,而不是 self['keys']
  • 若需强制统一行为,可将数据存在私有属性(如 _data),并在 __getattr__ 中只查 _data,不依赖 self[key]
  • 也可在初始化时预设保留字段黑名单(如 dir(Object) 或常见魔术方法名),绕过它们走 __getattr__

一个简洁可用的例子

下面是一个轻量封装字典的类,同时支持两种访问:

class DictLike:     def __init__(self, **kwargs):         self._data = kwargs 
def __getitem__(self, key):     return self._data[key]  def __getattr__(self, name):     try:         return self._data[name]     except KeyError:         raise AttributeError(f"'{self.__class__.__name__}' object has no attribute '{name}'")

使用示例:

obj = DictLike(name='Alice', age=30) print(obj['name'])  # 'Alice' print(obj.age)      # 30 print(obj.missing)  # AttributeError

text=ZqhQzanResources