タイトル通りです、知らなかったので自分用にメモ。
a.__call__()
と a()
は、オーバーライドしてみると実は挙動が違うということが分かる。
a()
は正確には type(a).__call__(a)
を呼んでいる、らしい。
>>> class A(object):
... def __init__(self):
... print 'init of A'
...
... def __call__(self):
... print 'call of A'
...
... def method(self):
... print 'method of A'
...
Aというクラスに __init__
, __call__
, method
を定義する。
methodは普通のメンバ関数だから、 a.method = hoge
などとすればメソッドのオーバーライドが可能。
# 普通に呼び出した時の処理を確認
>>> a = A()
init of A
>>> a.method()
method of A
>>> a()
call of A
# a.methodを上書きしてみる
>>> a.method = lambda: 'overriding method'
>>> a.method()
'overriding method'
# a.__call__も同じように上書きする
>>> a.__call__ = lambda: 'overriding call'
# a.__call__()の方は確かにオーバーライドされている
>>> a.__call__()
'overriding call'
# a()だとうまく行かない
>>> a()
call of A
>>> type(a).__call__(a)
call of A
# type(a).__call__を無理矢理上書きする
>>> type(a).__call__ = lambda a: 'new __call__'
>>> type(a).__call__(a)
'new __call__'
# うまく行った
>>> a()
'new __call__'