サーチ…


単純な記述子

ディスクリプタには2種類の種類があります。データ記述子は、 __get__() __set__()メソッドと__set__()メソッドの両方を定義するオブジェクトとして定義されますが、非データ記述子は__get__()メソッドのみを定義します。この区別は、オーバーライドとインスタンス辞書の名前空間を考慮する場合に重要です。データ記述子とインスタンス辞書のエントリが同じ名前を共有する場合は、データ記述子が優先されます。ただし、非データ記述子とインスタンス辞書のエントリが同じ名前を共有する場合、インスタンス辞書のエントリが優先されます。

呼び出されたときにはAttributeErrorを上げるセット ()の両方を取得 ()とset()を定義し、読み取り専用のデータ記述子を作成するには。例外を発生させるplaceholderを持つset ()メソッドを定義するだけで、データ記述子にすることができます。

descr.__get__(self, obj, type=None) --> value
descr.__set__(self, obj, value) --> None
descr.__delete__(self, obj) --> None

実装された例:

class DescPrinter(object):
    """A data descriptor that logs activity."""
    _val = 7
    
    def __get__(self, obj, objtype=None):
        print('Getting ...')
        return self._val

    def __set__(self, obj, val):
        print('Setting', val)
        self._val = val
    
    def __delete__(self, obj):
        print('Deleting ...')
        del self._val


class Foo():
    x = DescPrinter()       

i = Foo()
i.x
# Getting ...
# 7

i.x = 100
# Setting 100
i.x
# Getting ...
# 100

del i.x
# Deleting ...
i.x
# Getting ...
# 7

双方向のコンバージョン

Descriptorオブジェクトは、関連するオブジェクト属性が変更に自動的に反応することを許可します。

与えられた周波数(ヘルツ単位)と周期(秒単位)のオシレータをモデル化したいとします。期間を更新するには期間を更新し、期間を更新する場合は期間を更新する:

 >>> oscillator = Oscillator(freq=100.0)  # Set frequency to 100.0 Hz
>>> oscillator.period  # Period is 1 / frequency, i.e. 0.01 seconds
0.01
>>> oscillator.period = 0.02  # Set period to 0.02 seconds
>>> oscillator.freq # The frequency is automatically adjusted
50.0
>>> oscillator.freq = 200.0  # Set the frequency to 200.0 Hz
>>> oscillator.period  # The period is automatically adjusted
0.005

値(周波数、ヘルツ単位)の1つを「アンカー」、つまり変換なしで設定できるものとして選択し、そのためのディスクリプタクラスを作成します。

class Hertz(object):
    def __get__(self, instance, owner):
        return self.value

    def __set__(self, instance, value):
        self.value = float(value)

「その他」の値(期間、秒)は、アンカーの観点から定義されます。コンバージョンを行う記述子クラスを作成します。

class Second(object):
    def __get__(self, instance, owner):
        # When reading period, convert from frequency
        return 1 / instance.freq
    
    def __set__(self, instance, value):
        # When setting period, update the frequency
        instance.freq = 1 / float(value)

これで、Oscillatorクラスを書くことができます:

class Oscillator(object):
    period = Second()  # Set the other value as a class attribute

    def __init__(self, freq):
        self.freq = Hertz()  # Set the anchor value as an instance attribute
        self.freq = freq  # Assign the passed value - self.period will be adjusted


Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow