2013-06-21 110 views
0

我在Python 2.7倍在python中動態設置實例屬性/ memoized屬性?

class Example(object): 
    a = None 
    b = None 
    c = None 

現有示例類和現有的實例

anInstance = Example() 
anInstance.a = 100 
anInstance.b = 200 
anInstance.c = 300 

我已經重構/清理一些代碼,而且它現在已經知道,anInstance.c是一個昂貴的操作這很少使用。

在一個完美的世界裏,我只想做:

class Example(object): 
    _c = None 
    @property 
    def c(self): 
     if self._c is not None: 
      self._c = DO EXPENSIVE STUFF HERE 
     return self._c 

的問題是,我不能改變class Example現在。 [所以quickfix將它設置爲一個函數,並將每個obj.c更改爲obj.c()]

據我所知,沒有任何方法可以動態分配屬性/記憶,除非我改變對象。這種理解是否正確?我期待在這裏失望,我只是想要確認。

+0

當然,如果'obj.c'不是一個屬性,那麼它將在'Example .__ init__'中計算,在這種情況下,您必須修改'Example'?否則,爲什麼要使它成爲一個財產改變什麼? – katrielalex

+0

這是來自處理用戶狀態的webapp的一部分代碼。 __init__只是設置佔位符值。只有少數的請求才能有條件地計算出這個狀態;這個特定的屬性需要更少的次數。我沒有寫/設計這部分。我正在嘗試修復它。儘管我想把所有的東西都拿出來,但這不是一種選擇。 –

回答

4

你可以在事後改變Python類:

@property 
def c(self): 
    if self._c is None: 
     self._c = DO EXPENSIVE STUFF HERE 
    return self._c 

Example.c = c 
Example._c = None 

現在你已經添加了一個屬性c到類,以及添加_c屬性。

當然,您可能需要覆蓋該類上假定可以分配給self.c的任何現有方法。

動態添加或替換對象屬性的過程通常稱爲Monkey Patching

+0

當然,如果可以修改實例化'Example'的代碼,最好從'Example'繼承並創建子類實例。 – Marcin

+0

@Marcin:在這一點上,你需要修改引入'Example'的代碼。 –

+0

如果不修改monkeypatching,則不能修改。如果創建'Example'實例的地方數量有限,那麼只需要修改這些實例即可。 – Marcin