2016-02-09 59 views
0
class Bar: 

    def __init__(self, n): 
     self.n = n 

class Foo: 

    def __init__(self, l): 
     self.l = l 

x = Bar(2) 

# we want x.n to change whenever y.l changes 
y = Foo(x.n) 

# I'd like x.n to become 3 as a result 
y.l += 1 

print(x.n) 
>>> 2 

我該怎麼做才能從y以內更改x.n?沒有簡單的方法來做到這一點,但不添加更多的功能x如何更改對另一個對象屬性的引用的對象屬性的值?

+0

不,你不能用不可變對象來做到這一點。 – jonrsharpe

+0

你可以用間接方式來做,但是你不應該這樣做。你在這裏試圖解決什麼問題? –

+0

你必須對y使用setter函數,所以你不能說y.l + = 1,你必須說y.set(x,1)。然後y的setter應該照顧更新x和y。 Foo: def set(var,val): y.l + = val var.n = val –

回答

1

好,其他人已指出,這個問題歸結爲一個事實,即你'正在處理imutable objects。意識到這一點後,您應該使用可變類型,或使用回調來管理更新。阿德里亞諾阿布蘭特什使用了可變類型的替代的例子,但如果這不是你要找的內容,這裏有潛在的回調系統的一個例子:

# bad habit to be using the old style class definition (i.e. `class Foo:`) 
# the `@property` decorator wont work if you use the old style 

class Sync(object): 

    def __init__(self, name, value, *dependants): 
     """Sync the attribute `name` on all `dependants` when `self.value` is updated""" 
     self._name = name 
     self._value = value 
     self._updating = False 
     self._dependants = list(dependants) 
     self._update_dependants() 

    @property 
    def value(self): 
     return self._value 

    @value.setter 
    def value(self, x): 
     if x != self._value: 
      self._value = x 
      self._update_dependants() 

    def _update_dependants(self): 
     self._updating = True 
     for d in self._dependants: 
      if getattr(d, self._name) != self.value: 
       if isinstance(d, Sync): 
        if not d._updating: 
         setattr(d, self._name, self.value) 
       else: 
        setattr(d, self._name, self.value) 
     self._updating = False 

    def add_dependant(self, other): 
     self._dependants.append(other) 
     self._update_dependants() 

    def del_dependnant(self, other): 
     self._dependants.remove(other) 

    def __repr__(self): 
     return "Sync('"+self._name+"': "+repr(self.value)+")" 

    def __eq__(self, other): 
     if isinstance(other, Sync): 
      return self.value == other.value 
     else: 
      return self.value == other 

    def __ne__(self, other): 
     return not self.__eq__(other) 


s1 = Sync('value', 2) 
s2 = Sync('value', 1) 
print('setup the Sync objects:') 
print('>>> ' + repr(s1) + (' == ' if s1 == s2 else ' != ') + repr(s2)) 

s1.add_dependant(s2) 
s2.add_dependant(s1) 
print('add sync objects as dependants of each other:') 
print('>>> ' + repr(s1) + (' == ' if s1 == s2 else ' != ') + repr(s2)) 

s1.value += 1 
print('check that value changes transfer from one to the other:') 
print('>>> ' + repr(s1) + (' == ' if s1 == s2 else ' != ') + repr(s2)) 

如果這還不能滿足你,我就看看Traitlets。這是來自Ipython的一個包,它是Project Jupyter的一部分,它強制執行類型檢查,簡化回調系統並簡化應用程序配置。我一直在爲該項目做出貢獻,因此如果您對Traitlets有任何疑問,請隨時在這裏問我或在Gitter上發帖,開發團隊將回答他們。

+0

謝謝,由於這個答案以及上面的評論和編輯,我可能已經翻倍了我的編程詞彙。 –

0

我相信你在做什麼違背OOP的許多概念,但你可以使用一個列表:

class Bar: 
    def __init__(self,n): 
    self.n = [n] 

class Foo: 
    def __init__(self,l): 
    self.l = l 

x = Bar(2) 
print(x.n) 
>>>[2] 

y = Foo(x.n) 
y.l[0] += 1 
print(x.n) 
>>>[3] 
相關問題