TL;DR
特殊メソッドである__call__はインスタンスを関数オブジェクトとして扱う。__call__を実装したクラスでは、インスタンスを関数のように呼び出すことができる。
__call__ のポイント
- インスタンスを関数のように呼び出すことができる
- 関数を呼び出すよりスマートな書き方になる
関数の中身を dir()で見ると、__call__ が含まれている。
def func():
pass
dir(func)
#['__annotations__',
# '__call__',
# '__class__',
# '__str__',
# '__subclasshook__']
これは、関数オブジェクトが __call__ を実装した function クラスのインスタンスであることを示している。
通常、インスタンスを関数のように扱うとエラーが出る。
class A:
def __init__(self):
print('init')
a = A() # init
a() # エラーになる
次に__call__をつけてみると、インスタンスを関数のように扱うことができるようになる。
class A:
def __init__(self):
print('init')
def __call__(self):
print('call')
a = A() # init
a() # call
インスタンス、__call__、関数を比較。__call__を使うことで、関数を呼び出すよりスマートな書き方になる。
class A:
def __init__(self, x):
self.x = x
print(f'{x} init')
def __call__(self, y):
self.y = y
print(f'{self.x + y} call')
def func(self, z):
self.z = z
print(f'{self.x + z} func')
a = A(1) # 1 init
a.func(2) # 3 func
a(2) # 3 call