有没有一种方法可以在Python中为对象属性分配引用?

时间:2019-05-15 01:10:06

标签: python python-3.x

我想将一个对象的属性永久链接到另一个对象的属性,这样只要更改了后者,该对象就会自动更新。

我尝试使用使用=的简单分配,但这仅在分配时分配属性的值,而我想分配对属性本身的引用。

class firstObj:

    def __init__(self,n):
        self.name=n
        self.inA=1

    @property
    def outA(self):
        return self.inA+2

class secondObj:

    def __init__(self,n):
        self.name=n
        self.inA=1

    @property
    def outA(self):
        return self.inA*2




fo=firstObj("FO")
so=secondObj("SO")
fo.inA=so.outA

我正在尝试将so的输出链接到fo的输入

so.inA = 2
-> so.outA变为4
-> fo.inA变为4
-> fo.outA变为6

(通常,python中有一种方法可以将对变量的引用分配给另一个变量,而不是变量的值,以便a = b不会将b的值分配给a而是对b本身的引用)

3 个答案:

答案 0 :(得分:1)

python中的变量只是字典映射var name = value,如果您尝试print(globals()),它将注意到所有模块变量的字典映射

如果您需要实现所需的目标,可以在类定义中执行以下操作:

class firstObj:
    def __init__(self,n, obj=None):
        self.name=n
        self._inA=1 
        self.obj = obj

    @property
    def inA(self):
        if self.obj is not None:
            self._inA = self.obj.outA
        return self._inA

    @property
    def outA(self):
        return self.inA+2 


class secondObj:
    def __init__(self,n):
        self.name=n
        self.inA=1

    @property
    def outA(self):
        return self.inA*2


so=secondObj("SO")
fo=firstObj("FO", so)
# fo.inA=so.outA

so.inA=2
print(so.outA) # becomes 4
print(fo.inA) # becomes 4
print(fo.outA) # becomes 6

输出:

4
4
6

答案 1 :(得分:1)

在本机Python中,对此没有直接支持。但是,您可以使用回调模拟此功能:

from functools import partial

class Teller:

    def __init__(self, name):
        super().__setattr__('_callbacks', {})
        self.name = name

    def register(self, attr, callback):
        if attr in self._callbacks:
             self._callbacks[attr].append(callback)

        else:
            self._callbacks[attr] = [callback]

    def __setattr__(self, attr, value):
        if attr in self._callbacks:
            for callback in self._callbacks[attr]:
                callback(value)

        else:
            self._callbacks[attr] = []

        super().__setattr__(attr, value)

class Asker:

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

    def bind(self, self_attr, other, other_attr):
        other.register(other_attr, partial(setattr, self, self_attr))
        setattr(self, self_attr, getattr(other, other_attr))

teller = Teller('Teller')
teller.teller_value = 5
asker = Asker('Asker')
asker.bind('asker_value', teller, 'teller_value')

print(f'teller_value is now {teller.teller_value}')
print(f'asker_value is now {asker.asker_value}')

teller.teller_value = 10

print(f'teller_value is now {teller.teller_value}')
print(f'asker_value is now {asker.asker_value}')

输出:

teller_value is now 5
asker_value is now 5
teller_value is now 10
asker_value is now 10

基本上,这需要Asker的实例将其属性之一绑定到Teller的实例之一;然后,只要Teller实例修改该属性,Asker实例的相应属性也会更改。

答案 2 :(得分:0)

您不能这样做。 Python没有办法让名称引用另一个名称,这就是您想要的名称(您希望fo.inA引用so.outA)。名称只能引用值。这次讲座有更多详细信息:Python Names and Values