LoginSignup
22
19

More than 5 years have passed since last update.

a()とa.__call__()は等価ではない

Posted at

タイトル通りです、知らなかったので自分用にメモ。

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__'

参考

22
19
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
22
19