The goal is to write two classes that can be used in multiple inheritance without worying about order of said clases.
>>> class A(object):
... def __init__(self, a):
... self.a = a
... super(A, self).__init__(a)
...
>>> class B(object):
... def __init__(self, a):
... print 'do stuff with', a
...
>>> class C(object):
... def __init__(self, a):
... print 'do stuff with', a
... super(C, self).__init__(a)
...
>>> class V1(A, B):
... pass
...
>>> v1 = V1(123)
do stuff with 123
>>> print v1.a
123
>>> class V2(B, A):
... pass
...
>>> v2 = V2(123)
do stuff with 123
>>> print v2.a # fails, B.__init__ didn't call super()
Traceback (most recent call last):
File "<ipython-input-11-622b85d68966>", line 1, in <module>
print v2.a # fails, B.__init__ didn't call super()
AttributeError: 'V2' object has no attribute 'a'
>>> class V3(A, C):
... pass
...
>>> v3 = V3(123) # fails, object.__init__() takes no parameters
do stuff with 123
Traceback (most recent call last):
File "<ipython-input-13-92471b2623ee>", line 1, in <module>
v3 = V3(123) # fails, object.__init__() takes no parameters
File "<ipython-input-3-927193f9bdcf>", line 4, in __init__
super(A, self).__init__(a)
File "<ipython-input-5-5a5c7a030e38>", line 4, in __init__
super(C, self).__init__(a)
TypeError: object.__init__() takes no parameters
>>> class V4(C, A):
... pass
...
>>> v4 = V4(123) # fails, object.__init__() takes no parameters
do stuff with 123
Traceback (most recent call last):
File "<ipython-input-16-0a00995bd35b>", line 1, in <module>
v4 = V4(123) # fails, object.__init__() takes no parameters
File "<ipython-input-5-5a5c7a030e38>", line 4, in __init__
super(C, self).__init__(a)
File "<ipython-input-3-927193f9bdcf>", line 4, in __init__
super(A, self).__init__(a)
TypeError: object.__init__() takes no parameters
Heavy handed solution:
>>> class D(object):
... def __init__(self, a):
... print 'do stuff with', a
... mro = type(self).__mro__
... if D in mro and mro[mro.index(D) + 1:][:1] != (object,):
... super(D, self).__init__(a)
...
>>> class E(object):
... def __init__(self, a):
... self.a = a
... mro = type(self).__mro__
... if E in mro and mro[mro.index(E) + 1:][:1] != (object,):
... super(E, self).__init__(a)
...
>>> class V5(D, E):
... pass
...
>>> v5 = V5(123)
do stuff with 123
>>> print v5.a
123
>>> class V6(E, D):
... pass
...
>>> v6 = V6(123)
do stuff with 123
>>> print v6.a
123