问题
This is an extension to this question and raises a problem, which you, my fellow StackOverflowers, will hopefully be able to help me with. From the referenced question, consider the final code sample:
class A(object):
def __init__(self):
print "entering A"
print "leaving A"
class B(object):
def __init__(self):
print "entering B"
super(B, self).__init__()
print "leaving B"
class C(A,B):
def __init__(self):
print "entering c"
super(C, self).__init__()
print "leaving c"
As noted by the poster, when initialising C, the __init__
for B is never called. On considering Raymond Hettinger's post, the code for class A
should be modified to also call super().__init__()
:
class A(object):
def __init__(self):
print "entering A"
super(A, self).__init__()
print "leaving A"
We're all good so far. However, what if our class' __init__
functions accept arguments? Let's assume that all the __init__
functions accept a single argument and for consistency, we'll simply call it foo
, the code is now:
class A(object):
def __init__(self, foo):
print "entering A"
super(A, self).__init__(foo)
print "leaving A"
class B(object):
def __init__(self, foo):
print "entering B"
super(B, self).__init__(foo)
print "leaving B"
class C(A,B):
def __init__(self, foo):
print "entering c"
super(C, self).__init__(foo)
print "leaving c"
Here we hit a snag. When initialising any of the classes A, B or C, we eventually call object.__init__
with a single argument, foo
, which errors with TypeError: object.__init__() takes no parameters
. However, to remove one of the super().__init__
functions would mean the classes are no longer cooperative in the case of multiple inheritance.
After all that, my question is how does one get around this problem? It appears that multiple inheritance is broken in anything but cases where no arguments are passed to the __init__
functions.
UPDATE:
Rob in the comments suggests stripping keyword arguments (referenced in Raymond H's post). This actually works very well in the case of multiple inheritance until your change you code. If one of your functions no longer uses one of the keyword arguments and ceases to strip it without modifying the calling function, You will still receive the TypeError noted above. As such, this seems like a fragile solution for large projects.
回答1:
Admittedly, this solution may not be the most pythonic or ideal, but creating a wrapper class for object like so allows you to pass arguments around each __init__
in the inheritance:
class Object(object):
def __init__(self,*args,**kwargs):
super(Object,self).__init__()
class A(Object):
def __init__(self,*args,**kwargs):
super(A,self).__init__(*args,**kwargs)
class B(Object):
def __init__(self,*args,**kwargs):
super(B,self).__init__(*args,**kwargs)
class C(A,B):
def __init__(self,*args,**kwargs):
super(C,self).__init__(*args,**kwargs)
回答2:
My answer might be a little off. I've been looking for code to solve my particular problem. But after searching for hours I could not find good example. So I wrote this little test code. I think it is definitely cooperative multiple inheritance example. I really think someone might find it useful. So here we go!
Basically, I had a pretty big class that I wanted to split even further but due to my particular case it had to be the same class. Also all of my child classes had their own inits that I wanted to executed after base init so to speak.
Test Code
"""
Testing MRO Functionality of python 2.6 (2.7)
"""
class Base(object):
def __init__(self, base_arg, **kwargs):
print "Base Init with arg: ", str(base_arg)
super(Base, self).__init__()
def base_method1(self):
print "Base Method 1"
def base_method2(self):
print "Base Method 2"
class ChildA(Base):
def __init__(self, child_a_arg, **kwargs):
super(ChildA, self).__init__(**kwargs)
print "Child A init with arg: ", str(child_a_arg)
def base_method1(self):
print "Base Method 1 overwritten by Child A"
class ChildB(Base):
def __init__(self, child_b_arg, **kwargs):
super(ChildB, self).__init__(**kwargs)
print "Child B init with arg: ", str(child_b_arg)
def base_method2(self):
print "Base Method 2 overwritten by Child B"
class ChildC(Base):
def __init__(self, child_c_arg, **kwargs):
super(ChildC, self).__init__(**kwargs)
print "Child C init with arg: ", str(child_c_arg)
def base_method2(self):
print "Base Method 2 overwritten by Child C"
class Composite(ChildA, ChildB, ChildC):
def __init__(self):
super(Composite, self).__init__(base_arg=1, child_a_arg=2, child_b_arg=3, child_c_arg=4)
print "Congrats! Init is complete!"
if __name__ == '__main__':
print "MRO: ", str(Composite.__mro__), "\n"
print "*** Init Test ***"
test = Composite()
print "*** Base Method 1 Test ***"
test.base_method1()
print "*** Base Method 2 Test ***"
test.base_method2()
Output
MRO: (<class '__main__.Composite'>,
<class '__main__.ChildA'>,
<class '__main__.ChildB'>,
<class '__main__.ChildC'>,
<class '__main__.Base'>,
<type 'object'>)
*** Init Test ***
Base Init with arg: 1
Child C init with arg: 4
Child B init with arg: 3
Child A init with arg: 2
Congrats! Init is complete!
*** Base Method 1 Test ***
Base Method 1 overwritten by Child A
*** Base Method 2 Test ***
Base Method 2 overwritten by Child B
来源:https://stackoverflow.com/questions/16305177/cooperative-multiple-inheritance-issue