2014-06-11 56 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