2013-02-16 14 views
10

私は例えば、関連する複数の属性を持つクラスを持っている:クラスオブジェクトで、属性を自動更新する方法は?

class SomeClass: 
    def __init__(self, n=0): 
     self.list = range(n) 
     self.listsquare = [ x**2 for x in self.list ] 

私はオブジェクトを作成する場合は、通常、それは問題はないだろう、

a = SomeClass(10) 

で、私は2つのリスト、a.listを取得しますおよびa.listsquare

は今、私が最初に空のオブジェクトを作成し、そこに一つの属性を割り当てたい場合は、私は例えば、私は

b = SomeClass() 
b.list = range(5,10) 

行う場合、私はb.listsquareが自動的になりたい、他の属性を自動的に更新することにしたいです更新され、逆もまた同様です(b.listsquareと自動更新b.listを割り当てます)。これは可能ですか? クラスがこれに最適ですか?


皆さんありがとうございますが、私はすべての異なる回答に完全に圧倒されています。私は自分自身を書くことを学ぶことができる誰もが完全なソリューションを与えることができますか?私はa = Foo(3)を行う場合

  1. は、私が得るa.length = 3a.list = [0, 1, 2]a.listsquare = [0, 1, 4]

    私は3つの属性lengthlistとなるようにlistsquareでクラスFooを達成したいと思います。

  2. b = Foo().list = [5, 6]を実行すると、b.length = 2,b.listsquare = [25, 36]となります。
  3. c = Foo().listsquare = [4, 9]を実行すると、c.length = 2,c.list = [2, 3]となります。
+2

あなたは私たちが動作しません与えているコード)それはlistsquareを生成します。クラスは 'def'ではなく 'class'で定義され、 'def __init __(self、...)'メソッドで初期化されます。あなたは、 'self'という1つの必須パラメタと 'n'という1つのオプションのパラメタを持つ関数を定義しました。 SomeClass(10)を呼び出すと、関数は 'list'をオブジェクトに割り当てようとしますが失敗します。 - ああ、質問が再フォーマットされているように見えます...だから心配しないでください。 – tdelaney

+0

申し訳ありませんが、私は修正を行いました。私は今それをよく知らない。 – LWZ

答えて

13

を別のプロパティに更新のためにプロパティを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] 
+0

これは、3つのプロパティ( 'size'、' list'、 'listsquare')を定義する必要があることを意味しますか? – LWZ

+0

これは正しいです。私はあなたが望むように動作するように上記の答えを更新しました - サイズ属性はもう必要な感じです。 –

4

絶対に。代わりにpropertyを使用してください。

class SomeClass(object): 
    def __init__(self, n=5): 
    self.mylist = range(n) 

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

a = SomeClass() 
a.mylist = [4, 5, 8] 
print a.listsquare 

読み取り者の練習として、プロパティ値のキャッシュが残っています。

+0

素晴らしい!他の方法はどうですか? 'a.listsquare'を定義して' a.mylist'を取得できますか? – LWZ

+0

はい。あなたの財産にセッターを追加するだけです。 –

2

あなたはまた、ちょうどこのように、setterメソッドを使用することができます。

class SomeClass: 
    def __init__(self, n=5): 
     self.set_list(range(n)) 

    def set_list(self, n): 
     self.list = n 
     self.listsquare = [ x**2 for x in self.list ] 

b = SomeClass() 
b.set_list(range(5,10)) 
1

イグナシオの@propertyソリューションは素晴らしいですが、それはリストにあなたがlistsquareを参照するたびに再計算 - 高価得ることができます。 Mathewのソリューションは素晴らしいですが、今は関数呼び出しがあります。これらを「プロパティ」機能と組み合わせることができます。ここで私はgetterとmy_list用のセッターを定義します(私はそれを 'list'と呼ぶことはできませんでした!

class SomeClass(object): 

    def __init__(self, n=5): 
     self.my_list = range(n) 

    def get_my_list(self): 
     return self._my_list 

    def set_my_list(self, val): 
     self._my_list = val 
     # generate listsquare when my_list is updated 
     self.my_listsquare = [x**2 for x in self._my_list] 

    # now my_list can be used as a variable 
    my_list = property(get_my_list, set_my_list, None, 'this list is squared') 

x = SomeClass(3) 
print x.my_list, x.my_listsquare 
x.my_list = range(10) 
print x.my_list, x.my_listsquare 

この出力:

[0, 1, 2] [0, 1, 4] 
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] 
+0

あなたが指摘してくれたおかげで、私はリストを間違って初期化しました。 – tdelaney

関連する問題