2012-03-07 28 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) 
相关问题