2012-03-07 35 views
2

我有這樣的代碼:在一個實例中,如何檢測類成員是否被新實例成員替換?

class ReplaceableClass(Object): 
    def __init__(self, x): 
     self.x = [x] 

    def movedata(self, old): 
     self.x = old.x + self.x 

class Example(Object): 

    myThing = ReplaceableClass(1) 

e = Example() 

e.myThing = ReplaceableClass(2) 

它如何能工作,如果我取代由以下塊中的最後一行?

myNewThing = ReplaceableClass(2) 
myNewThing.movedata(e.myThing) 
e.myThing = myNewThing 

所以e.myThing.x等於[1,2]而不是[2]。

我試圖通過描述符,但因爲它會導致一個無限循環無法分配一個新的對象:

class ReplaceableClass(Object): 

    [...] 

    def __set__(self,a,b): 
     for p in dir(a): 
      if self==getattr(a,p): 
       self.movedata(b) 
+0

這可能*可能*但它肯定不會是慣用的,明智的,可維護的,理智的,有用的或品味良好的。 – delnan 2012-03-07 17:38:00

+0

對不起,我的問題太模糊了,不知道它可能有多有用。 – DiThi 2012-03-07 17:52:37

+0

無論它可能出現多麼有用,其他缺點都會將其取消,並導致淨虧損。記住:顯式比隱式更好。 – delnan 2012-03-07 18:00:44

回答

1

有兩種選擇:

  • 使用self.__dict__movedata到避免無限循環。 self.__dict__是包含實例中所有屬性的原始字典;如果直接訪問該詞典,則不會調用描述符API使用的方法。

  • 如果你只有幾個屬性,你可以使用屬性API(見the property() function),而不是它允許你做一些事情,當一個特定的屬性發生變化(在這種情況下,這將是myThing)。

+0

「屬性api」是什麼意思? – Marcin 2012-03-07 17:40:33

+0

@Marcin'財產'我打賭。 – delnan 2012-03-07 17:44:34

+0

謝謝!移動數據後使用'a .__ dict __ [p] = b'就像我想要的那樣工作! – DiThi 2012-03-07 17:51:49

0

如果我捉住了主意,你可以這樣做一樣簡單

class Example(object): 
    myThing = (1,) 

e = Example() 
e.myThing+= (2,) 

>>> e.myThing 
(1, 2) 
>>> Example.myThing 
(1,) 

如果你需要更多的功能,可以擴展tuple或創建自己的不可變集合:

from itertools import chain 
class ReplaceableClass(object): 
    def __init__(self, *x): 
     self._data = tuple(x) 

    def __add__ (self, other): 
     return ReplaceableClass(*(chain(self, other))) 

    def __iter__(self): 
     return iter(self._data) 


    def __repr__(self): 
     return 'ReplaceableClass(%s)'%(', '.join(map(repr,self._data))) 

class Example(object): 
    myThing = ReplaceableClass(1) 

e = Example() 
e.myThing+= (2,3) 

>>> e.myThing 
ReplaceableClass(1, 2, 3) 
>>> Example.myThing 
ReplaceableClass(1) 
相關問題