hermy wrote: > Hi, > I'm trying to figure out how to pass constructor arguments to my > superclasses in a multiple inheritance situation. > > As I understand it, using super() is the preferred way to call > the next method in method-resolution-order. When I have parameterless > __init__ methods, this works as expected. > However, how do you solve the following simple multiple inheritance > situation in python ? > > class A(object): > def __init__(self,x): > super(A,self).__init__(x) > print "A init (x=%s)" % x > > class B(object): > def __init__(self,y): > super(B,self).__init__(y) > print "B init (y=%s)" % y > > class C(A,B): > def __init__(self,x,y): > super(C,self).__init__(x,y) <-------- how to do this ??? > print "C init (x=%s,y=%s)" % (x,y) > > What I want is that when I create a class C object > x = C(10,20) > that the x argument of C's __init__ is used to initialize the > A superclass, and the y argument is used to initialize the B > superclass. > In C++, I would do this using initilaization lists, like: > C::C(int x, int y) : A(x), B(y) { ... }
Well, technically, you can't do this in C++ at all. A little explanation. In multiple inheritance situations, Python has a significant difference from regular C++ inheritance: in C++, if you multiply-inherit from two different classes that both inherit from the same base class, the resulting structure has two copies of the data associated with the base class. In Python, only there is only one copy. If you want only one copy of the base class's data in C++, you must use virtual inheritance. But here's the thing: in C++, you can't initialize a virtual base class in the constructor. A virtual base class is always initialized with the default constructor. The reason for this is obvious: otherwise, you could end up initializing the virtual base twice with different arguments. This also explains why, in Python, super is preferred for multiple inheritance: it guarantees that each base class's __init__ is called only once. This comes at the price of less flexibility with the function arguments, but in Python, at least you can use function arguments. So now, let's talk about solutions. Now that we know why super is preferred, we can make a somewhat intelligent decision whether to go against the advice. If you know your inheritance hierarchy is not going to have any two classes inheriting from the same base class (except for object), then you could just call each class's __init__ directly, same as you would have done with old-style classes. There is no danger of initializing any base class twice and no reason for super to be preferred here. A.__init__(self,x) B.__init__(self.y) But if you can't or don't want to do this, you'll have to make some concessions with the argument lists. One thing to do would have A and B both accept x and y, using only the one it needs. A more general approach might be to use keyword arguments. For example (you can improve upon this): class A(object): def __init__(self,**kwargs): use(kwargs['x']) class B(object): def __init__(self,**kwargs): use(kwargs['y']) class C(A,B): def __init__(self,**kwargs): super(C,self).__init__(**kwargs) C(x=1,y=2) > I'm probably overlooking some basic stuff here, Unfortunately, it doesn't appear that you are. You'll have to choose between calling base class __init__s old-style, or fiddling with their argument lists. Carl Banks -- http://mail.python.org/mailman/listinfo/python-list