LoginSignup
1
2

More than 3 years have passed since last update.

pythonのディスクリプター

Posted at

ディスクリプターとは下記のようなメソッドを備えたクラスのことである。

メソッド 呼び出しタイミング
get(self,obj,type) アトリビュートを取得するとき
set(self,obj,value) アトリビュートを設定するとき
delete(self,obj) アトリビュートを削除するとき

getattr, setattrなどの特殊メソッドとは異なるメソッドであるため、ディスクリプターとは区別して認識する必要がある。

・アトリビュート操作に関わる挙動を別クラスに切り出せる(=クラスをまたがるアトリビュート関連の機能を再利用できる。)
・特定のアトリビュートに対してのみ適用される挙動を定義できる。(getattr, setattrでは、そのクラスのすべてのアトリビュートに影響)

な丼メリットがあります。ディスクリプターは、プロパティをはじめ、クラス/静的メソッド、superなどの背後でも利用されています。

descriptor_basic.py
#ディスクリプターの定義
class LogProp:
    def __init__(self,name): #1
        self.name = name #1

    #アトリビュートを取得するときの処理
    def __get__(self,obj,type): #2
        prin(f'{self.name}:get') #2,6
        return obj.__dict__[self.name] #2,4

    #アトリビュートを設定するときの処理
    def __set__(self,obj,value) #3
        prin(f'{self.name}:set{value}') #3,7
        obj.__dict__[self.name] = value #3,5

class App:
    #ディスクリプターの定義
    title = LogProp('title') #8

if __name__ == '__main__':
    app = App()
    app.title = '独習Python' #9
    print(app.title) #9

ディスクリプターの側で定義しているのは、init, get, setです。まず、initメソッド(#1)は、ディスクリプターの対象となるアトリビュート名を受け取り、これを保存しています。後で値を受け渡しするためのキーとなる情報です。

そして、set(#2), get(#3)が値受け渡しのための主となるメソッドです。get, setは、引数経由で以下の情報を受け取ります。

obj:対象となるインスタンス
type:対象となるクラス
value:渡された値

この例であれば、dictを介してインスタンスの値を取得、参照しています。get, setはインスタンスのアトリビュート操作を肩代わりするので、なんらかの値の取得、保存操作が無い場合アトリビュート値の取得、設定は無効になります。

コード中の#4,5のような記述を最低限とし、取得、設定時の追加的な操作を加えておきましょう。この例であれば、取得、設定の結果をprintで出力しています。

定義済みのディスクリプターをアトリビュートに紐づけるには、#8のようにします。(これはproperty関数でプロパティを定義するのと同じ書き方です。)

コード中の#9のようにtitleを設定・sy津億したタイミングでログが出力されることが確認できます。

独習python 第11章オブジェクト指向構文 より引用

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2