2016-09-29 7 views
0

は、私は非常によく似た質問に対して、この答えを見てきました:クラスオブジェクトでは、リストの1つのエントリだけを変更したときに属性を自動更新する方法はありますか?

:私は使用してリストを更新するとき、このコードで

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] 

In class object, how to auto update attributes?

が、私はここにコードを貼り付けます

>>> 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は更新されません:私は、リスト内の項目を1つだけ変更したときに

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

にはどうすればlistsquare自動更新を行うことができますか?

答えて

1

あなたができる方法の1つは、listクラスとほぼ同じですがowner属性を持つプライベートヘルパー_Listクラスを持つことです。 _Listインスタンスの要素の1つに値が割り当てられるたびに、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] 
1

まずは、1つのlist.setterにアクセスして2つの異なる属性を変更しないことをおすすめします。その理由は:

>>> 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] 
関連する問題