Python 将变量设置为对象时,请将其设置为中的所有嵌套对象

Python 将变量设置为对象时,请将其设置为中的所有嵌套对象,python,oop,attributes,decorator,python-decorators,Python,Oop,Attributes,Decorator,Python Decorators,我有以下有效的代码: class fundamental_object(): def __init__(self,x): self.x = x class encapsulator_object(): def __init__(self,x,obj_list): self._x = x self.obj_list = obj_list @property def x(self): return

我有以下有效的代码:

class fundamental_object():

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

class encapsulator_object():

    def __init__(self,x,obj_list):
        self._x = x
        self.obj_list = obj_list

    @property
    def x(self):
        return self.x

    @x.setter
    def x(self,new_x):
        print('in setter!')
        self._x = new_x
        for obj in self.obj_list:
            obj.x = new_x

if __name__ == '__main__' :
    x = 10
    obj_1 = fundamental_object(x)
    obj_2 = fundamental_object(x)
    obj_list = [obj_1,obj_2]
    encapsulator = encapsulator_object(x,obj_list)

    encapsulator.x = 20
    print(encapsulator._x)
    print(obj_1.x) # all of these are also updated to 20.
正如您所看到的,其思想是,每当我更改封装器对象的属性“x”时,我都希望其中的所有嵌套对象(基本对象)也用这个新变量“x”更新。然而,从用户的角度来看,这很快就会令人困惑,因为如果我理解正确,“x”是“基本对象”的整数,而“x”是“封装器对象”的方法,要实际访问封装器中的整数,我需要使用“\x”。是否有任何简单/正确/通灵的方法来实现以下功能:

    x = 10
    obj_1 = fundamental_object(x)
    obj_2 = fundamental_object(x)
    obj_list = [obj_1,obj_2]
    encapsulator = encapsulator_object(x,obj_list)

    encapsulator.x = 20
    print(encapsulator.x) # notice the underscore is now gone!  
    print(obj_1.x)        # this would be updated to 20 as well

我知道有可能使“基本对象”也有“\ux”作为整数变量,这会在一定程度上减少混淆,但是,如果可能的话,我想完全去掉下划线!(现在我得到一个无限递归)。谢谢

检查此代码。我只是在你的属性中更改了你的getter方法。现在它指向
自身

class fundamental_object():
    def __init__(self, x):
        self.x = x


class encapsulator_object():
    def __init__(self, x, obj_list):
        self._x = x
        self.obj_list = obj_list

    @property
    def x(self):
        return self._x   # -----> here

    @x.setter
    def x(self, new_x):
        print('in setter!')
        self._x = new_x
        for obj in self.obj_list:
            obj.x = new_x


if __name__ == '__main__':
    x = 10
    obj_1 = fundamental_object(x)
    obj_2 = fundamental_object(x)
    obj_list = [obj_1, obj_2]
    encapsulator = encapsulator_object(x, obj_list)

    encapsulator.x = 20
    print(encapsulator.x)  # notice the underscore is now gone!
    print(obj_1.x)  # this would be updated to 20 as well
或者,您可以完全删除
封装器\u对象
中的
x
\u x
。然后在getter中,您可以在
self.obj_列表中找到
x

class fundamental_object():
    def __init__(self, x):
        self.x = x


class encapsulator_object():
    def __init__(self, obj_list):
        self.obj_list = obj_list

    @property
    def x(self):
        return self.obj_list[0].x

    @x.setter
    def x(self, new_x):
        print('in setter!')
        for obj in self.obj_list:
            obj.x = new_x

请记住,在本例中,因为我们决定选择列表中的第一项,所以所有对象必须具有相同的
x
值。不过,在你成为二传手之后,没有必要担心这一点。如果您想在setter之前调用getter,我提到了它。

您的
封装器\u object.x
属性是无限递归的。你的意思是“回归自我”。谢谢你的回答。事实上,第一个是有效的,所以我接受它作为一个答案。然而,我仍然有一部分人觉得很难说服用户需要下划线(如果他们决定输入代码)。它的目的是什么?它只是一个中间变量,允许setter方法执行我想要的操作?@Zepphit第二部分也可以,只需从
enclosurator=enclosurator\u对象(x,obj\u列表)
中删除
x
,因为它不再需要了。我们消除了
x
。如果确保传递到列表中的所有对象都具有相同的
x
属性,则使用第二个属性。如果没有,请确保先调用
设置器
,然后再调用第二个设置器。这里没有下划线,谢谢,但是由于self.obj_列表[0].x部分,我觉得使用第二种方法不舒服。我仍然希望封装器_对象本身有自己的“变量”,而不是引用它们自己对象中的变量。另一个在外面会更好,但在我看来仍然不理想。。。