この記事では、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のディスクリプタについて解説しました。
使いこなせばかなり色々できそうなポテンシャルを感じますね〜😄 ディスクリプタはまだまだ奥深いのでさらに学びたい方は公式ドキュメントを参照してください。
それでは今回の内容はここまでです。ではまたどこかで〜( ・∀・)ノ