2014-06-11 57 views
1

我有以下代碼:鏈接的名稱到另一個名稱

class B: 

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

class A: 

    def __init__(self, msg): 
     self.msg = msg 
     self.b = B(self.msg) 

    def update(self, msg): 
     self.msg = msg 

a = A('hello') 

print a.msg 
print a.b.msg 

a.update('bye') 

print a.msg 
print a.b.msg 

它打印:

hello 
hello 
bye 
hello 

這不是我想要的。我需要的是a.b.msga.msga.b.msg「鏈接」,即使在重新綁定a.msg後,也必須始終引用與a.msg相同的對象。這可能嗎?我怎樣才能做到這一點?

+0

他們是否是字符串? – wnnmaw

+2

在'update'方法中添加'self.b.msg = msg'? –

+0

@IsmailBadawi:這是我想避免的。我希望自動發生,而不是手動強制。背景是,我可以使用父數據的很多子對象作爲緩存屬性,我甚至無法枚舉。 – dangonfast

回答

0

你可以使用一個屬性:

class A(object): 
    def __init__(self, msg): 
    self.b = B(msg) 

    @property 
    def msg(self): 
    return self.b.msg 

    @property.setter 
    def msg(self, value): 
    self.b.msg = value 

我有這樣一個小的向後相比,你想要什麼。在這裏,我總是將a.msg鏈接到a.b.msg,而不是其他方式,但它實際上主要是語義。這些變化看起來應該傳播到兩個方向,所以應該沒什麼實際的區別。

+0

我不想更新self.b.msg:還有self.c.msg,...,一個不確定的數字:對象本身是緩存的屬性,我無法枚舉。 – dangonfast

1

你的實際問題是,你想要的行爲類似於C++中的引用調用。爲了達到這個目的,你可以做的就是用一些小技巧來模擬一個內存位置。 Found here這個工作原因可以在this questions accepted answer找到,它與Pythons可變和不可變對象有關。

class ref: 
    def __init__(self, obj): self.obj = obj 
    def get(self): return self.obj 
    def set(self, obj):  self.obj = obj 

class B: 
    def __init__(self, msg): 
     self.msg = msg 

class A: 
    def __init__(self, msg): 
     self.msg = ref(msg) 
     self.b = B(self.msg) 

    def update(self, msg): 
     self.msg.set(msg) 

a = A('hello') 

print a.msg.get() #hello 
print a.b.msg.get() #hello 

a.update('bye') 

print a.msg.get() #bye 
print a.b.msg.get() #bye 

但如果這意味着你的代碼太多的變化,你也可以做的是在每一個功能定義一個方法msg(self)msg,重命名msgmessage或什麼的。 這樣你就可以通過調用a.msg()來獲得字符串,例如對現有代碼的更改較少。但是我擔心沒有任何改變你的代碼的辦法來解決你的問題。

樣品兩種,配有msg()方法:

class B: 
    def __init__(self, msg): 
     self.message = msg 

    def msg(self): 
     return self.message.get() 

class A: 
    def __init__(self, msg): 
     self.message = ref(msg) 
     self.b = B(self.message) 

    def update(self, msg): 
     self.message.set(msg) 

    def msg(self): 
     return self.message.get() 

a = A('hello') 

print a.msg() #hello 
print a.b.msg() #hello 

第三種解決方案,我看是使用一個List,而不是引用類:

class B: 
    def __init__(self, msg): 
     self.msg = msg 

class A: 
    def __init__(self, msg): 
     self.msg = [msg] 
     self.b = B(self.msg) 

    def update(self, msg): 
     self.msg[0] = msg 

a = A('hello') 

print a.msg[0] #hello 
print a.b.msg[0] #hello 

a.update('bye') 

print a.msg[0] #bye 
print a.b.msg[0] #bye 

一般來說,你可以使用任何其他但請注意,您不能重新分配某些「子類」中的可變對象,如B在您的示例中。

+0

這很有趣,但不得不添加'.get()'意味着我的代碼 – dangonfast

+0

@ jeckyll2hide很多更改抱歉,這是我腦海中最好的想法......我會更新,如果我找到更好的,更容易使用的方式! – Theolodis

+0

@ jeckyll2hide我更新了我的答案。 – Theolodis

1

爲什麼不能b跟蹤a並使用a.msg獲取其msg

class MockA: 
    def __init__(self, msg): 
     self.msg = msg 

class B: 

    def __init__(self, a): 
     if isinstance(a, A): 
      self._a = a 
     else: 
      self._a = MockA(a) 

    @property 
    def msg(self): 
     return self._a.msg 

class A: 

    def __init__(self, msg): 
     self.msg = msg 
     self.b = B(self) 

    def update(self, msg): 
     self.msg = msg 

a = A('hello') 

print a.msg 
print a.b.msg 

a.update('bye') 

print a.msg 
print a.b.msg 

b = B('here') 

print b.msg 

打印:

hello 
hello 
bye 
bye 
here