Python

【Python】ディスクリプタの使い方

この記事では、Pythonのディスクリプタ(Descriptor)について解説します。ディスクリプタを使うことで、属性の書き込み、読み込み、削除する際の動作をカスタマイズすることができます。それでは、ディスクリプタの使い方を見ていきましょう❗️

ディスクリプタとは

ディスクリプタとは、ディスクリプタプロトコルのメソッドが1つでも定義されているオブジェクトのことを言います。

ディスクリプタプロトコル
  • descr.__get__(self, obj, type=None) –> value
  • descr.__set__(self, obj, value) –> None
  • descr.__delete__(self, obj) –> None

上記の3つのメソッドいずれかを定義したオブジェクトを属性として参照させることで、それぞれのメソッドに対応した動作をオーバーライドすることができます。

それぞれのメソッドが定義する動作は以下の通りです。

__get__ 属性が参照された際の動作を定義します
__set__ 属性が更新された際の動作を定義します
__delete__ 属性が削除された際の動作を定義します

それでは、実際に定義して挙動を確かめてみましょう!

ディスクリプタの定義

ディスクリプタは以下のように定義します。

class ディスクリプタ名:

    def __init__(self):
        # 省略可能
        
    def __get__(self, obj, objtype=None):
        # 参照する際の動作の定義
        return 戻り値

    def __set__(self, obj, value)
        # 更新する際の動作の定義

    def __delete__(self, obj)
        # 削除する際の動作の定義

定義したディスクリプタをオブジェクトの属性として参照させます。

class クラス名:

    変数名 = ディスクリプタ名()

あとは普通にインスタンス化し、その変数にアクセスすることで、ディスクリプタプロトコルで定義した動作を呼び出すことができます。

インスタンス名 = クラス名()

インスタンス名.変数名
>> __get__が呼び出される

インスタンス名.変数名 = なんかしらの値
>> __set__が呼び出される

del インスタンス名.変数名
>> __delete__が呼び出される

サンプル

以下のサンプルでは、ディスクリプタで動的にプライベートな_valueを生成しています。ポイントは、MyClassクラスのコンストラクタでインスタンス変数を初期化する際にもディスクリプタが呼び出されることです。

# ディスクリプタ
class Descriptor:
        
    def __get__(self, obj, objtype=None):
        print('__get__')
        return obj._value

    def __set__(self, obj, value):
        print('__set__')
        obj._value = value

    def __delete__(self, obj):
        print('__delete__')
        del obj._value


class MyClass:

    value = Descriptor()

    def __init__(self, value):
        self.value = value


mc = MyClass(1)
>> __set__

print(mc.value)
>> __get__
>> 1

mc.value = 100
>> __set__

# ディスクリプタで動的に生成された「_value」にもアクセスできる
print(mc._value)
>> 100

del mc.value
>> __delete__

まとめ

この記事では、Pythonのディスクリプタについて解説しました。

使いこなせばかなり色々できそうなポテンシャルを感じますね〜😄 ディスクリプタはまだまだ奥深いので、さらに学びたい方は公式ドキュメントを参照してください。

それでは今回の内容はここまでです。ではまたどこかで〜( ・∀・)ノ

最短3か月でエンジニア転職『DMM WEBCAMP COMMIT』