Python 在类对象中,当您仅更改列表的一个条目时,如何自动更新属性?

Python 在类对象中,当您仅更改列表的一个条目时,如何自动更新属性?,python,class,attributes,Python,Class,Attributes,我看到了一个非常相似的问题的答案: 我将在此处粘贴代码: class SomeClass(object): def __init__(self, n): self.list = range(0, n) @property def list(self): return self._list @list.setter def list(self, val): self._list = val

我看到了一个非常相似的问题的答案:

我将在此处粘贴代码:

class SomeClass(object):
    def __init__(self, n):
        self.list = range(0, n)

    @property
    def list(self):
        return self._list
    @list.setter
    def list(self, val):
        self._list = val
        self._listsquare = [x**2 for x in self._list ]

    @property
    def listsquare(self):
        return self._listsquare
    @listsquare.setter
    def listsquare(self, val):
        self.list = [int(pow(x, 0.5)) for x in val]

>>> c = SomeClass(5)
>>> c.listsquare
[0, 1, 4, 9, 16]
>>> c.list
[0, 1, 2, 3, 4]
>>> c.list = range(0,6)
>>> c.list
[0, 1, 2, 3, 4, 5]
>>> c.listsquare
[0, 1, 4, 9, 16, 25]
>>> c.listsquare = [x**2 for x in range(0,10)]
>>> c.list
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
在此代码中,当我使用以下命令更新列表时:

>>> c.list = [1, 2, 3, 4]
c、 listsquare将相应更新:

>>> c.listsquare
[1, 4, 9, 16]
但当我尝试时:

>>> c.list[0] = 5
>>> c.list
[5, 2, 3, 4]
Listsquares未更新:

>>> c.listsquare
[1, 4, 9, 16]

当我只更改列表中的一项时,如何使listsquare自动更新?

一种方法是使用一个私人助手
\u list
类,它几乎与内置的
列表
类完全相同,但也有一个
所有者
属性。每当一个
\u列表
实例的元素被赋值时,它就可以修改其
所有者
listsquare
属性,使其保持最新。由于它仅由
SomeClass
使用,因此可以将其嵌套在其中以提供更多的封装

class SomeClass(object):
    class _List(list):
        def __init__(self, owner, *args, **kwargs):
            super(SomeClass._List, self).__init__(*args, **kwargs)
            self.owner = owner

        def __setitem__(self, index, value):
            super(SomeClass._List, self).__setitem__(index, value)
            self.owner.listsquare[index] = int(value**2)

    def __init__(self, n):
        self.list = SomeClass._List(self, range(0, n))

    @property
    def list(self):
        return self._list
    @list.setter
    def list(self, val):
        self._list = val
        self._listsquare = [x**2 for x in self._list ]

    @property
    def listsquare(self):
        return self._listsquare
    @listsquare.setter
    def listsquare(self, val):
        self.list = [int(pow(x, 0.5)) for x in val]

c = SomeClass(5)
print(c.list)        # --> [0, 1, 2, 3, 4]
print(c.listsquare)  # --> [0, 1, 4, 9, 16]
c.list[0] = 5
print(c.list)        # --> [5, 1, 2, 3, 4]
print(c.listsquare)  # --> [25, 1, 4, 9, 16]

一种方法是使用一个私人助手
\u List
类,它几乎与内置的
List
类完全相同,但也有一个
所有者
属性。每当一个
\u列表
实例的元素被赋值时,它就可以修改其
所有者
listsquare
属性,使其保持最新。由于它仅由
SomeClass
使用,因此可以将其嵌套在其中以提供更多的封装

class SomeClass(object):
    class _List(list):
        def __init__(self, owner, *args, **kwargs):
            super(SomeClass._List, self).__init__(*args, **kwargs)
            self.owner = owner

        def __setitem__(self, index, value):
            super(SomeClass._List, self).__setitem__(index, value)
            self.owner.listsquare[index] = int(value**2)

    def __init__(self, n):
        self.list = SomeClass._List(self, range(0, n))

    @property
    def list(self):
        return self._list
    @list.setter
    def list(self, val):
        self._list = val
        self._listsquare = [x**2 for x in self._list ]

    @property
    def listsquare(self):
        return self._listsquare
    @listsquare.setter
    def listsquare(self, val):
        self.list = [int(pow(x, 0.5)) for x in val]

c = SomeClass(5)
print(c.list)        # --> [0, 1, 2, 3, 4]
print(c.listsquare)  # --> [0, 1, 4, 9, 16]
c.list[0] = 5
print(c.list)        # --> [5, 1, 2, 3, 4]
print(c.listsquare)  # --> [25, 1, 4, 9, 16]

首先,我建议您不要通过访问single list.setter来更改两个不同的属性。原因是:

>>> c.list[0] = 5
>>> c.list
[5, 2, 3, 4]
>>> c.listsquare
[1, 4, 9, 16]
不工作,是吗,您正在访问c.list.\uuu setitem\uuu方法

c.list[0] = 5 
is equal to
c.list.__setitem__(0, 5)
or
list.__setitem__(c.list, 0, 5)
and as such, the list.__setitem__ method isn't the one you've implemented in your class.
但是,如果您确实想这样做,您应该重新考虑基于self.\u list创建方形列表

class SomeClass(object):
    def __init__(self, n):
        self.list = range(0, n)

    @property
    def list(self):
        return self._list

    @list.setter
    def list(self, val):
        self._list = val

    @property
    def listsquare(self):
        return [n ** 2 for n in self.list]

    @listsquare.setter
    def listsquare(self, val):
        self.list = [int(pow(x, 0.5)) for x in val]

首先,我建议您不要通过访问single list.setter来更改两个不同的属性。原因是:

>>> c.list[0] = 5
>>> c.list
[5, 2, 3, 4]
>>> c.listsquare
[1, 4, 9, 16]
不工作,是吗,您正在访问c.list.\uuu setitem\uuu方法

c.list[0] = 5 
is equal to
c.list.__setitem__(0, 5)
or
list.__setitem__(c.list, 0, 5)
and as such, the list.__setitem__ method isn't the one you've implemented in your class.
但是,如果您确实想这样做,您应该重新考虑基于self.\u list创建方形列表

class SomeClass(object):
    def __init__(self, n):
        self.list = range(0, n)

    @property
    def list(self):
        return self._list

    @list.setter
    def list(self, val):
        self._list = val

    @property
    def listsquare(self):
        return [n ** 2 for n in self.list]

    @listsquare.setter
    def listsquare(self, val):
        self.list = [int(pow(x, 0.5)) for x in val]