Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/353.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 将一个名称链接到另一个名称_Python_Reference - Fatal编程技术网

Python 将一个名称链接到另一个名称

Python 将一个名称链接到另一个名称,python,reference,Python,Reference,我有以下代码: 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.

我有以下代码:

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
。这可能吗?我如何才能做到这一点?

您可以使用一个属性:

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
,而不是反过来,但实际上在这一点上主要是语义。这些变化应该是双向传播的,所以实际上没有什么实际差异。

< P>你的实际问题是,你想要一个类似于C++中引用调用的行为。要实现这一点,您可以做的是使用一些小技巧来模拟内存位置。其工作的原因可以在中找到,它与python的可变和不可变对象有关

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
重命名为
message
或其他任何内容。 这样,您可以通过调用
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
我看到的第三种解决方案是使用
列表
,而不是引用类:

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
,在您的示例中。

为什么
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

它们必须是字符串吗?在
update
方法中添加
self.b.msg=msg
。我希望这是自动发生的,而不是用手强迫。背景是,我可以使用父对象的数据作为缓存属性拥有许多子对象,我甚至无法枚举这些子对象。@wnnmaw:它们可以是字符串,也可以是其他内容。解决方案应支持任何类型的对象字符串,因为它们是不可变的。我不想更新self.b.msg:还有self.c.msg,…,一个不确定的数字:对象本身是缓存属性,我无法枚举。这很有趣,但必须添加
.get()
意味着对我的code@jeckyll2hide很抱歉这是我想到的最好的主意。。。我会更新,如果我找到一个更好,更容易使用的方式@我更新了我的答案。