20

重複の可能性:
Python でプロパティを使用するのではなく、ディスクリプタ クラスのインスタンスをクラス属性に割り当てるのは、いつ、どのような場合ですか?

プロパティと記述子をいつ使用するかについて混乱しています。プロパティは特殊な記述子であると読みました。

誰かがこれがどのように機能するかを投稿できますか?

4

2 に答える 2

23

記述子が実際に何であるかについてのドキュメントを読む必要があります。Cliff's Notes バージョン: 記述子は、アクセスされるオブジェクトの属性にフックできるようにする低レベルのメカニズムです。プロパティは、これの高レベルのアプリケーションです。つまり、プロパティは記述子を使用して実装されます。または、さらに良いことに、プロパティは標準ライブラリで既に提供されている記述子です。

属性の読み取りから計算された値を返す、または属性の書き込みで関数を呼び出す簡単な方法が必要な場合は、@propertyデコレータを使用します。記述子 API はより柔軟性がありますが、不便であり、この状況では間違いなく「やり過ぎ」で非慣用的です。バインドされたメソッド、または静的メソッドとクラス メソッドの実装など、より高度なユース ケースに役立ちます。たとえば、属性が型オブジェクトまたは型のインスタンスを介してアクセスされたかどうかを知る必要がある場合。

于 2012-10-11T18:27:58.357 に答える
14

あなたはここから両方についてもっと読むことができます。しかし、これは同じ本の簡単な例で、本質的に同じ問題が何であるかを解決する違いを説明しようとしています。ご覧のとおり、プロパティを使用した実装ははるかに簡単です。

属性値を取得および設定するためのPythonの内部メカニズムを利用する方法はいくつかあります。最もアクセスしやすい手法は、プロパティ関数を使用して、属性名に関連付けられたget、set、およびdeleteメソッドを定義することです。プロパティ関数は、記述子を作成します。少しアクセスしにくいですが、より拡張可能で再利用可能な手法は、記述子クラスを自分で定義することです。これにより、かなりの柔軟性が得られます。これを行うには、get、set、およびdeleteメソッドを定義するクラスを作成し、記述子クラスを属性名に関連付けます。

プロパティ関数は、個別のクラスを定義せずに単純な記述子を実装するための便利な方法を提供します。完全なクラス定義を作成するのではなく、getterおよびsetterメソッド関数を記述して、これらの関数を属性名にバインドできます。

記述子の例:

class Celsius( object ):
    def __init__( self, value=0.0 ):
        self.value= float(value)
    def __get__( self, instance, owner ):
        return self.value
    def __set__( self, instance, value ):
        self.value= float(value)

class Farenheit( object ):
    def __get__( self, instance, owner ):
        return instance.celsius * 9 / 5 + 32
    def __set__( self, instance, value ):
        instance.celsius= (float(value)-32) * 5 / 9

class Temperature( object ):
    celsius= Celsius()
    farenheit= Farenheit()
>>>
oven= Temperature()
>>>
oven.farenheit= 450
>>>
oven.celsius
232.22222222222223
>>>
oven.celsius= 175
>>>
oven.farenheit
347.0

プロパティの例:

class Temperature( object ):
    def fget( self ):
        return self.celsius * 9 / 5 + 32
    def fset( self, value ):
        self.celsius= (float(value)-32) * 5 / 9
    farenheit= property( fget, fset )
    def cset( self, value ):
        self.cTemp= float(value)
    def cget( self ):
        return self.cTemp
    celsius= property( cget, cset, doc="Celsius temperature" )
>>>
oven= Temperature()
>>>
oven.farenheit= 450
>>>
oven.celsius
232.22222222222223
>>>
oven.celsius= 175
>>>
oven.farenheit
347.0
于 2012-10-11T18:33:38.737 に答える