Ключевым моментом для понимания этого является super()
для реализации кооперативного наследования. Как классы взаимодействуют, решать программисту. super()
не волшебство и не знает точно, что вы хотите! Нет смысла использовать super для плоской иерархии, которая не нуждается в кооперативном наследовании, поэтому в этом случае предложение S. Lott является точным. Подклассы Useful могут или не могут использовать super()
в зависимости от своих целей:)
Например: Abstract - A. A <- B, но вы хотите поддержать вставку C, например, A <- C <- B. </p>
class A(object):
"""I am an abstract abstraction :)"""
def foo(self):
raise NotImplementedError('I need to be implemented!')
class B(A):
"""I want to implement A"""
def foo(self):
print('B: foo')
# MRO Stops here, unless super is not A
position = self.__class__.__mro__.index
if not position(B) + 1 == position(A):
super().foo()
b = B()
b.foo()
class C(A):
"""I want to modify B and all its siblings (see below)"""
def foo(self):
print('C: foo')
# MRO Stops here, unless super is not A
position = self.__class__.__mro__.index
if not position(C) + 1 == position(A):
super().foo()
print('')
print('B: Old __base__ and __mro__:\n')
print('Base:', B.__bases__)
print('MRO:', B.__mro__)
print('')
# __mro__ change implementation
B.__bases__ = (C,)
print('B: New __base__ and __mro__:\n')
print('Base:', B.__bases__)
print('MRO:', B.__mro__)
print('')
b.foo()
А на выходе:
B: foo
B: Old __base__ and __mro__:
Base: (<class '__main__.A'>,)
MRO: (<class '__main__.B'>, <class '__main__.A'>, <class 'object'>)
B: New __base__ and __mro__:
Base: (<class '__main__.C'>,)
MRO: (<class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
B: foo
C: foo