2017-10-02 5 views
1

python 2.7を使用して、私はTestクラスを新しいスタイルのクラス構文で定義します。新しいスタイルのクラスと古いスタイルのクラスでsetterが異なる動作をする理由

class Test(object): 
    def __init__(self): 
    self._a = 5 

    @property 
    def a(self): 
    return self._a 

    @a.setter 
    def a(self, val): 
    self._a = val 

t = Test() 
print t.a 
t.a = 4 
print t.a 
print t._a 

上記のコードを実行すると、希望する動作である5,4,4が印刷されます。 しかし、上記のコードの最初の行をclass Test:に変更すると、結果は5,4,5になります。

出力にこの違いが生じる原因を知っている人はいますか?

答えて

2

記述子は、旧式のクラスで呼び出されることが保証されていないです。 docsから:

属性アクセスのデフォルトの動作を設定、取得、または オブジェクトの辞書から属性を削除することです。例えば、a.xは、a.__dict__['x']で始まり、 type(a).__dict__['x']で始まり、メタクラスを除いて type(a)の基本クラスを続けて、 ルックアップチェーンを持ちます。ルックアップされた値が記述子メソッドの1つを定義するオブジェクト である場合、Pythonは デフォルト動作をオーバーライドし、代わりに記述子メソッドを呼び出すことができます。この が優先順位チェーンで発生するところは、どの記述子メソッド が定義されているかによって異なります。 記述子は、新しいスタイル オブジェクトまたはクラス(オブジェクトから継承する場合、クラスは新しいスタイル、 タイプ)に対してのみ呼び出されることに注意してください。

だから、何ここで起こっていることはTest.a.__set__が起動しないさんということです、あなたは単に追加されa属性tへ:本当にT.a.__get__作業を行い、なぜあなたはで驚きべきこと

In [8]: class Test: 
    ...: def __init__(self): 
    ...:  self._a = 5 
    ...: 
    ...: @property 
    ...: def a(self): 
    ...:  return self._a 
    ...: 
    ...: @a.setter 
    ...: def a(self, val): 
    ...:  self._a = val 
    ...: 

In [9]: t = Test() 

In [10]: vars(t) 
Out[10]: {'_a': 5} 

In [11]: t.a 
Out[11]: 5 

In [12]: t._a 
Out[12]: 5 

In [13]: t.a = 100 

In [14]: t.a 
Out[14]: 100 

In [15]: t._a 
Out[15]: 5 

In [16]: vars(t) 
Out[16]: {'_a': 5, 'a': 100} 

ここにすべて

その答えは、Python 2.2では古いスタイルのクラスが記述子を使用するために再実装され、それが依存するべきではない実装の詳細です。 this質問とリンクissueを参照してください。

説明文を使用している場合は、新しいスタイルのクラスでのみ使用してください。私は新しいスタイルのクラスを使用する場合

注意は、それが必要として動作します。

In [17]: class Test(object): 
    ...: def __init__(self): 
    ...:  self._a = 5 
    ...: 
    ...: @property 
    ...: def a(self): 
    ...:  return self._a 
    ...: 
    ...: @a.setter 
    ...: def a(self, val): 
    ...:  self._a = val 
    ...: 

In [18]: t = Test() 

In [19]: vars(t) 
Out[19]: {'_a': 5} 

In [20]: t.a = 100 

In [21]: t.a 
Out[21]: 100 

In [22]: t._a 
Out[22]: 100 

In [23]: vars(t) 
Out[23]: {'_a': 100} 
関連する問題