如何从静态方法创建类的实例?

时间:2010-03-11 16:24:05

标签: python

这是我的问题。我创建了一个非常繁重的只读类,使用静态“工厂”方法进行许多数据库调用。此方法的目标是,如果已存在相同对象(相同类型,相同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')

感谢。

3 个答案:

答案 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]