Pythonでの継承クラスから基底クラスのメソッド呼び出しにおけるsuper関数の振る舞い
Pythonで継承したクラスが基底クラスのメソッドを呼び出しする場合に
2種類の方法があるようです。
# -*- coding: cp932 -*- class A(object): def test(self, x): return x class B(A): def test2(self, x): return super(B, self).test(x) #super関数を使ってBの上位クラスを呼び出す def test3(self, x): return A.test(self, x) #Aのインスタンス.test(x)と同じ if __name__ == '__main__': b = B() print b.test2('abc') print b.test3('def')
実行結果は下のようになります。
abc def
Pythonライブラリリファレンスでのsuper関数の説明では
super(type[, object-or-type])
type の上位クラスを返します。返された上位クラスオブジェクトが非バインドの場合、二つめの引数は省略されます。二つめの引数がオブジェクトの場合、isinstance(obj, type) は真でなくてはなりません。二つ目の引数が型オブジェクトの場合、issubclass(type2, type) は真でなくてはなりません。 super() は新スタイルのクラスにのみ機能します。
と上位クラスを返すと書いてあるのですが、
書いたコードを考えてみると「super(B, self)」と「A」は同じじゃないのかな?と混乱してきました
もし同じだったらsuper(B, self).test(x)のtestメソッド呼び出しにselfも渡す必要があるはずです。
いろいろ調べる中、下のコードを書いて実行すると
class A(object): def test(self, x): return x class B(A): def __init__(self): self.hoge = super(B, self).test self.hoga = A.test if __name__ == '__main__': b = B() print b.hoge print b.hoga
その結果は
<bound method B.test of <__main__.B object at 0x0204A430>> <unbound method A.test>
となりました。
bound methodやunbound methodって何だろうと思って検索したところ、詳しく説明してるところがありました。
http://d.hatena.ne.jp/tomapd/20060427/1146135987
Python においてメソッドはユニークな性質を持っており、bound されているか unbound か、明確な違いがある。bound / unbound とは、そのメソッドが特定のインスタンスに属しているか、いないかという言い方が出来ると思う。
unbound メソッドを使うためには、"self" に相当するインスタンスを与える必要がある。
一方で、bound メソッドは関数として使うことができる。
ということでsuper関数を用いて参照したメソッドはbound methodでそのまま関数として使える。
そしてクラスから参照したメソッドはunbound methodで「A.test(self, x)」のようにインスタンスを渡さなければいけない。
結果として「super(B, self)」と「A」は同じではないということのようです。
混乱しているけど合っているのだろうか。