2010-03-11 224 views
1

這是我的問題。我創建了一個非常繁重的只讀類,使用靜態「工廠」方法進行多個數據庫調用。此方法的目標是避免在已經創建的對象池中查找同一對象(相同類型,相同的初始參數)的相同實例已經存在的情況下查殺數據庫。如何從靜態方法創建類的實例?

如果發現有問題,該方法將返回它。沒問題。但是,如果不是,我怎麼可以創建一個對象的實例,以繼承的方式工作?

>>> 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') 

謝謝。

+1

爲什麼這麼複雜?爲什麼不簡單'getInstance(A,'foo')'或'getInstance(b,'bar')'? – 2010-03-11 16:57:45

+0

實際的課程比示例中的課程稍微複雜一些。這部分只是一個失蹤,實際上:) – Pierre 2010-03-12 10:27:10

回答

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(標識)多次,只要你喜歡,以獲得相同的對象。如果我已經正確理解了你的話,那就是cls(identifier),它會觸發數據庫,​​並且你不想經常打電話,因爲你知道對象是不可變的。

如果您想保留緩存中的對象,即使它們不再被其他地方引用,那麼將WeakValueDictionary更改爲正常的字典。

這要求標識符適用於字典鍵,如果它是一個字符串,就像您在示例代碼中那樣,那麼它就是。

+0

非常感謝你。正是我在找什麼。你理解我正確:) – Pierre 2010-03-11 17:01:45

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) 

我們將池與池中的對象分開。他們沒有任何關係。

您可以繼承所有您想要的對象的子類。

您可以 - 獨立 - 更改池化策略,而不會中斷或重新測試彙集的對象。

+0

是的,謝謝。事實上,我想要做的不是真正的共同池。我不想讓許多班級做同樣的事情,並根據需要選擇一個班級。我只有一個給定init參數的實例(例如用戶ID),並且我希望每次都返回正確的實例,而無需將其從池中移除(該類支持併發訪問,因爲它是隻讀的。 ) – Pierre 2010-03-11 16:38:28

+0

「我希望每次都返回正確的實例,而不將其從池中移除」。你的意思是你想要一個對象字典? – 2010-03-11 16:56:07

0

擴展在美國洛特的評論:

「我想回到每次都正確的情況下 ,而不 池中移除」。你的意思是你想要一個 字典的對象? -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] 
相關問題