Python中如何实现Class[key]语法从类静态容器提取实例数据?
报错原因
你遇到的报错本质是Python特殊方法的查找规则导致的:
- 调用
实例[key]时,Python会去实例所属的类中查找__getitem__方法,因此你原来代码里的b["foo"]可以正常运行 - 调用
类[key]时,Python会去类所属的元类(默认是type)中查找__getitem__方法,默认的type没有实现该方法,因此抛出TypeError: 'type' object is not subscriptable
你写的元类实现评估
你的元类方案功能上是可用的,没有基础逻辑错误,但是存在几个可优化的问题:
- 存储用
set实现,每次查询都要遍历所有实例,时间复杂度为O(n),实例数量多的时候性能差 - 没有做id重复校验,多个实例使用相同id时只会返回第一个匹配的结果,不会触发提示
- 存储使用强引用持有实例,即使实例在业务逻辑中已经不再使用,也不会被垃圾回收,会造成内存泄漏
__getitem__直接返回name属性,灵活性不足,后续需要获取实例其他属性时需要修改元类逻辑
优化后的实现方案
from weakref import WeakValueDictionary class MetaBucket(type): def __init__(cls, name, bases, dct): # 使用弱引用字典存储,实例无外部引用时自动释放 cls._bucket = WeakValueDictionary() def __getitem__(cls, key): # O(1) 时间复杂度查询,找不到时抛出KeyError和原生dict行为对齐 return cls._bucket[key] # 兼容原有的get方法调用习惯 def get(cls, key, default=None): return cls._bucket.get(key, default) class Bucket(metaclass=MetaBucket): def __init__(self, id, name): self.id = id self.name = name # 新增id重复校验 if id in self.__class__._bucket: raise ValueError(f"实例id {id} 已存在") self.__class__._bucket[id] = self
使用示例:
b = Bucket("foo", "bar") print(Bucket["foo"].name) # 输出 bar print(Bucket.get("foo").name) # 输出 bar print(Bucket.get("not_exist", "默认值")) # 输出 默认值
内容的提问来源于stack exchange,提问作者OPPenguin
相关产品推荐
相关产品推荐

