您可能想使用lru_cache。如果你的类定义是
@lru_cache(maxsize=32)
class C(object):
def __init__(self, num):
self.num = num
然后它的行为就像
>>> a = C(1)
>>> a.num = 2
>>> b = C(1)
>>> b.num
2
>>> a is b
True
但是,这使名称C
成为一个函数,并且在类实际实例化之前,任何类功能都不可用。如果需要,也可以直接缓存__new__
负责创建对象的方法。 __new__
是一个方法,它接受所有相同的参数,并且在我们创建类实例__init__
之前调用它。__init__
由于缓存 的输出__new__
很简单,我们可以让事情变得更有趣。让我们创建一个新的装饰器,它的工作方式与 类似lru_cache
,但它可以与类一起使用来缓存 的输出__new__
:
def lru_cache_class(maxsize):
def wrap(klass):
@lru_cache(maxsize=maxsize)
def new(cls, *args, **kwargs):
self = object.__new__(cls)
return self
klass.__new__ = new
return klass
return wrap
我们提供__new__
所有可能的参数和关键字参数,以便它也可以与其他类一起使用。现在我们可以像这样缓存类的实例C2
:
@lru_cache_class(maxsize=32)
class C2(object):
def __init__(self, num):
self.num = num
我们可以看到对象被缓存了:
>>> c = C2(2)
>>> c is C2(2)
True
然而,与第一种方法相比,这种方法还有另一个细微的差别。例如:
>>> d = C2(3)
>>> d.num = 4
>>> d.num
4
>>> e = C2(3)
>>> d.num == e.num
>>> d.num
3
这种行为是预期的,因为__init__
无论如何都会调用,尽管对象的内存位置保持不变。根据您的用例,您可能还希望缓存的输出__init__
。