Carl Banks schreef:
> 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
Thanx, I think I got it (please correct me if I'm wrong):
o super(C,self) determines the next class in the inheritance hierarchy
according to
method resolution order, and simply calls the specified method on it
(in this case
__init__ with the specified argument list.
o since I cannot now beforehand where my class will appear in the
inheritance
hierarchy when __init__ is called, I need to pass on all the
arguments and let
my method decide which ones to use.
On the other hand, when I use old-style, s.a. B.__init__(args), I
specify statically
in which class the method lookup should occur.
Unfortunately, new and old style don't mix well (as I found out by
experimenting a little),
so for new code I