Python PR

【Python】ディスクリプタの使い方について解説

記事内に商品プロモーションを含む場合があります

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

ディスクリプタを使うことでユーザー定義クラスの属性の書き込み、読み込み、削除する際の動作をカスタマイズすることができます。

それでは、ディスクリプタの使い方を見ていきましょう❗️

ディスクリプタとは?

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

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

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

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

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

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

ディスクリプタの使い方

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

  • STEP1
    定義

    クラスとしてディスクリプタを定義します。

    class ディスクリプタ名: def __init__(self): # 省略可能 def __get__(self, obj, objtype=None): # 参照する際の動作の定義 return 戻り値 def __set__(self, obj, value) # 更新する際の動作の定義 def __delete__(self, obj) # 削除する際の動作の定義
  • STEP2
    参照
    定義したディスクリプタをオブジェクトの属性として参照させます。

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

    インスタンス名 = クラス名() インスタンス名.変数名 # __get__が呼び出される インスタンス名.変数名 = なんかしらの値 # __set__が呼び出される del インスタンス名.変数名 # __delete__が呼び出される

サンプル

以下のコードでは、ディスクリプタで動的にプライベートな_valueを生成しています。

# ディスクリプタ 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__

ポイントは、MyClassクラスのコンストラクタでインスタンス変数を初期化する際にもディスクリプタが呼び出されることです。

まとめ

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

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

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

  • Descriptor HowTo Guide — Python 3.9.5 documentation