我有以下代码:
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.msg
是"链接"到a.msg
:a.b.msg
必须始终引用与a.msg
相同的对象,即使在重新绑定a.msg
之后也是如此。这可能吗?我怎么能这样做?
答案 0 :(得分:1)
您的实际问题是,您希望行为类似于C ++中的引用调用。要实现这一点,您可以做的是使用一点hack来模拟内存位置。 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
,将msg
重命名为{{1} }} 管他呢。
这样,您可以通过调用message
来获取String,这表示对现有代码的更改较少。但我担心如果不对代码进行任何更改,就无法解决问题。
示例二,使用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
一样。
答案 1 :(得分: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
答案 2 :(得分: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
而不是相反,但在这一点上它实际上主要是语义。这些变化似乎应该向两个方向传播,因此应该没有什么实际差异。