繁体   English   中英

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

[英]In class object, how to auto update attributes when you change only one entry of a 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
        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自动更新?

一种实现方法是拥有一个私人助手_List类,该类几乎完全类似于内置list类,但还具有一个owner属性。 每次为_List实例的元素之一分配一个值时,它便可以修改其ownerlistsquare属性以使其保持最新状态。 由于它仅由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]

首先,我建议您不要通过添加单个list.setter来更改两个不同的属性。 这样做的原因:

>>> c.list[0] = 5
>>> c.list
[5, 2, 3, 4]
>>> c.listsquare
[1, 4, 9, 16]

不起作用,是因为您要使用c.list .__ setitem__方法。

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._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]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM