Python以外でクラスを使ったプログラムを作成すると、クラスをインスタンスした時にはコンストラクタが呼ばれ、クラスオブジェクトを解放した時にはデストラクタが呼ばれます。
コンストラクタやデストラクタのように、ある特定の操作をクラスオブジェクトに対して行った時に呼ばれるメソッドをPythonでは特殊メソッド(Special Method)といいます。
Pythonではインスタンスした時や解放した時以外にも様々な特殊メソッドがあります。
(参考)
特殊メソッドはアンダーバー2つ(__)で前後が挟まれたメソッド名となります。
Deep Learningのプログラムでは比較的この特殊メソッドが使われるので、実際に使った事のある特殊メソッドを紹介します。
__init__(self [, …])
コンストラクタ
クラスがインスタンスされた時に呼ばれます。
__del__(self)
デストラクタ
del object のように、クラスが解放される時に呼ばれます。
ただし、呼ばれない場合もあります。
どちらかというと、挙動はファイナライザに近いです。
__call__(self [, …])
object(a, b, c)のように、クラスオブジェクトに引き数を追加し、クラスオブジェクトをメソッドのように呼び出します。
__len__(self)
len(object)のようにした時に、要素数(int型)を返します。
何の要素数か?は特に規定はなくユーザー次第となります。
__getitem__(self, key)
object[1]のように、クラスオブジェクトに角カッコ付きで配列のように呼び出した時に要素を返します。
__setitem__(self, key, value)
object[1] = 3のように、クラスオブジェクトに角カッコ付きで配列のように、要素を設定します。
__delitem__(self, key)
del object[key] のようにクラスオブジェクトに角カッコ付きで配列の削除のように呼び出した時に要素を削除します。
サンプル
y = a0 + a1*x + a2*x^2+ a3*x^3 +… となるようなn次関数の係数をコンストラクタで設定し、xの値を__call__メソッドで呼び出し、yの値を取得するサンプルです。
class TestClass:
'''
y = a0 + a1*x + a2*x^2+ a3*x^3 +・・・の計算
'''
def __init__(self, a):
''' コンストラクタ '''
print("__init__")
self.coeff = a
def __del__(self):
''' デストラクタ '''
print("__del__")
def __call__(self, x):
''' 呼び出し可能オブジェクト '''
print("__call__")
sum = 0
for i in range(len(self.coeff)):
sum += self.coeff[i] * x**i
return sum
def __len__(self):
''' 要素数 '''
print("__len__")
return len(self.coeff)
def __getitem__(self, index):
''' 指定した番号の要素取得 '''
print("__getitem__")
return self.coeff[index]
def __setitem__(self, index, value):
''' 指定した番号の要素設定 '''
print("__setitem__")
self.coeff[index] = value
def __delitem__(self, index):
''' 指定した番号の要素削除 '''
print("__delitem__")
del self.coeff[index]
#------------------------------------------------------
# クラスのインスタンス(__init__メソッドの呼び出し)
object = TestClass([2, 1.5, 3]) # y = 2 + 1.5*x + 3*x**2
# __call__メソッドの呼び出し
print(object(3.5))
# 要素数(__len__メソッドの呼び出し)
print(len(object))
# 要素の取得(__getitem__メソッドの呼び出し)
print(object[1])
# 要素の設定(__setitem__メソッドの呼び出し)
object[1] = 0.5
print(object[1])
# 要素の削除(__delitem__メソッドの呼び出し)
del object[2]
print(len(object))
# クラスの解放
del object
(実行結果)
まとめ
個人的には特殊メソッドはコンストラクタ以外は、あまり使う事はないのですが、例えば画像処理で特殊メソッドを駆使するとすると、ガウシアンフィルタのような畳み込みフィルタでは、コンストラクタでカーネルの係数を設定し、__call__メソッドで画像データを引き数で渡して、フィルタ後の画像データを取得するような使い方ができると思います。
特殊メソッドの呼び出され方は決まっていますが、実際にどのようにつかうか?はユーザー次第なので、うまく使えば、キレイなコードを書く事ができると思います。
コメント