あなたのコードはメソッド解決の順序とは何の関係もありません。メソッドの解決は、例の場合とは異なり、多重継承の場合に行われます。self.__class__
これは、メソッドが定義されているクラスと実際には同じクラスであり、これが間違っていると想定しているため、コードは単純に間違っています。
>>> class A(object):
... def __init__(self):
... print self.__class__
...
>>>
>>> class B(A):
... def __init__(self):
... A.__init__(self)
...
>>> B()
<class '__main__.B'>
<__main__.B object at 0x1bcfed0>
>>> A()
<class '__main__.A'>
<__main__.A object at 0x1bcff90>
>>>
したがって、いつ電話する必要があるか:
super(B, self).__init__(1, b, c)
あなたは確かに呼んでいます:
# super(self.__class__, self).__init__(1, b, c)
super(C, self).__init__(1, b, c)
編集:質問にもっとよく答えようとしています。
class A(object):
def __init__(self, a):
for cls in self.__class__.mro():
if cls is not object:
cls._init(self, a)
def _init(self, a):
print 'A._init'
self.a = a
class B(A):
def _init(self, a):
print 'B._init'
class C(A):
def _init(self, a):
print 'C._init'
class D(B, C):
def _init(self, a):
print 'D._init'
d = D(3)
print d.a
プリント:
D._init
B._init
C._init
A._init
3
(テンプレートパターンの修正バージョン)。
現在、親のメソッドは実際には暗黙的に呼び出されますが、コードが読みにくく、ゲインが低いため、明示的が暗黙的よりも優れているpythonzenに同意する必要があります。ただし、すべての_init
メソッドが同じパラメーターを持っていることに注意してください。親を完全に忘れることはできません。そうすることはお勧めしません。
単一継承の場合、より良いアプローチは、を呼び出さずに親のメソッドを明示的に呼び出すことsuper
です。そうすることで、現在のクラスに名前を付ける必要はありませんが、それでも親のクラスが誰であるかを気にする必要があります。
良い読み物は次のとおりです:how-does-pythons-super-do-the-right-thingとその質問で提案されたリンク、特にPythonのSuperは気の利いたものですが、使用することはできません
階層が変更される可能性がある場合は、設計が不適切であり、そのコードを使用しているすべての部分に影響を与えるため、推奨されるべきではありません。
編集2
別の例が思い浮かびますが、これはメタクラスを使用しています。Urwidライブラリは、メタクラスを使用して属性をクラスに格納する__super
ため、その属性にアクセスするだけで済みます。
元:
>>> class MetaSuper(type):
... """adding .__super"""
... def __init__(cls, name, bases, d):
... super(MetaSuper, cls).__init__(name, bases, d)
... if hasattr(cls, "_%s__super" % name):
... raise AttributeError, "Class has same name as one of its super classes"
... setattr(cls, "_%s__super" % name, super(cls))
...
>>> class A:
... __metaclass__ = MetaSuper
... def __init__(self, a):
... self.a = a
... print 'A.__init__'
...
>>> class B(A):
... def __init__(self, a):
... print 'B.__init__'
... self.__super.__init__(a)
...
>>> b = B(42)
B.__init__
A.__init__
>>> b.a
42
>>>