如何将缓存实例的元类用作其子类的__metaclass__?
使用缓存元类的方法
首先先把你给出的元类代码补全(看起来最后一行有点截断),完整的可运行版本大概是这样:
class _CachingMeta(type): __cache__ = {} def __init__(self, n, b, d): # 这里可以添加你的自定义初始化逻辑 super(_CachingMeta, self).__init__(n, b, d) def __call__(cls, *a, **kw): # 生成缓存键,注意参数必须是可哈希的 key = frozenset((cls, frozenset(a), frozenset(kw.items()))) if key not in _CachingMeta.__cache__: _CachingMeta.__cache__[key] = super(_CachingMeta, cls).__call__(*a, **kw) return _CachingMeta.__cache__[key]
接下来分Python版本说明如何将这个元类应用到子类上:
Python 3 写法
在Python 3中,指定元类最直接的方式是在类定义时使用metaclass关键字参数:
class MyCachedClass(metaclass=_CachingMeta): def __init__(self, value): self.value = value # 测试缓存效果 obj1 = MyCachedClass(10) obj2 = MyCachedClass(10) print(obj1 is obj2) # 输出 True,说明是同一个实例
Python 2 写法
在Python 2中,需要在类内部定义__metaclass__属性:
class MyCachedClass: __metaclass__ = _CachingMeta def __init__(self, value): self.value = value # 测试缓存效果 obj1 = MyCachedClass(10) obj2 = MyCachedClass(10) print(obj1 is obj2) # 输出 True
补充说明
- 你的元类通过重写
__call__方法拦截了类的实例化过程,只有当对应的缓存键不存在时才会创建新实例,否则直接返回缓存中的实例。 - 注意缓存键使用了
frozenset,这要求你的位置参数*a和关键字参数**kw中的所有元素都必须是可哈希类型(比如不能是列表、字典这类可变且不可哈希的对象),否则会抛出TypeError。
内容的提问来源于stack exchange,提问作者dr-igor
相关产品推荐
相关产品推荐

