这是我的问题。我创建了一个非常繁重的只读类,使用静态“工厂”方法进行许多数据库调用。此方法的目标是,如果已存在相同对象(相同类型,相同init参数)的相同实例,则通过查看已创建对象池来避免数据库被杀死。
如果找到了某些内容,该方法将返回它。没问题。但如果没有,我怎样才能以继承的方式创建对象的实例?
>>> class A(Object):
>>> @classmethod
>>> def get_cached_obj(self, some_identifier):
>>> # Should do something like `return A(idenfier)`, but in a way that works
>>> class B(A):
>>> pass
>>> A.get_cached_obj('foo') # Should do the same as A('foo')
>>> A().get_cached_obj('foo') # Should do the same as A('foo')
>>> B.get_cached_obj('bar') # Should do the same as B('bar')
>>> B().get_cached_obj('bar') # Should do the same as B('bar')
感谢。
答案 0 :(得分:4)
import weakref
class A(object):
_get_obj_cache = weakref.WeakValueDictionary()
@classmethod
def get_obj(cls, identifier):
cache = cls._get_obj_cache
obj = cache.get((cls, identifier))
if obj is None:
obj = cache[(cls, identifier)] = cls(identifier)
return obj
class B(A):
pass
因为使用了WeakValueDictionary,只要您有任何其他引用,对象将保持缓存,您可以根据需要多次调用SomeClass.get_obj(identifier)来获取相同的对象。如果我理解正确的话,那就是cls(identifier)
,它会触及数据库以及你不想频繁调用的内容,因为你知道这些对象是不可变的。
如果要将对象保留在缓存中,即使它们不再在别处引用,也可以将WeakValueDictionary更改为普通字典。
这要求标识符适用于dict键,如果它是您在示例代码中的字符串,那么它就是。
答案 1 :(得分:1)
通常的做法是这样。
class SomeClass( object ):
# Something that is precious and needs to be pooled.
class SomeClassPool( object ):
def __init__( self ):
self.pool= [ SomeClass() ]
def getInstance( self ):
if len(self.pool) == 0:
self.pool.append( SomeClass() )
# maybe allocate several, depends on the costs
return self.pool.pop()
def release( self, anInstance ):
self.pool.append( anInstance )
我们将池与正在合并的对象分开。他们彼此无关。
您可以将所有想要的对象子类化。
您可以 - 独立 - 更改合并策略,而不会破坏或重新测试合并的对象。
答案 2 :(得分:0)
扩展S.Lott的评论:
“我想返回正确的实例 每一次,而不是从中删除它 游泳池“。你的意思是你想要一个 对象词典? -S.Lott
the_cache = {}
def get_obj(cls, identifier):
key = (cls, identifier)
if key not in the_cache:
the_cache[key] = cls(identifier)
return the_cache[key]
或
def get_obj(cls, identifier):
key = (cls, identifier)
try:
return the_cache[key]
except KeyError:
the_cache[key] = cls(identifier)
return the_cache[key]