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