multiple inheritance super()

P

Peter Hansen

km said:
Hi all,

In the following code why am i not able to access class A's object attribute - 'a' ? I wishto extent class D with all the attributes of its base classes. how do i do that ?

thanks in advance for enlightment ...

here's the snippet

#!/usr/bin/python

class A(object):
def __init__(self):
self.a = 1

class B(object):
def __init__(self):
self.b = 2

class C(object):
def __init__(self):
self.c = 3

class D(B, A, C):
def __init__(self):
self.d = 4
super(D, self).__init__()

Each class should do a similar super() call, with the appropriate name
substitutions.

Calls to __init__ must be made explicitly in subclasses, including in
the case of multiple inheritance.

Also note that often (usually) you would like the __init__ call to come
*before* other location initializations, and it's the safest thing to do
unless you have clear reasons to the contrary.

-Peter
 
R

rafi

Peter said:
km said:
Hi all,

In the following code why am i not able to access class A's object
attribute - 'a' ? I wishto extent class D with all the attributes of
its base classes. how do i do that ?
[snip]
Each class should do a similar super() call, with the appropriate name
substitutions. [snip]
-Peter

A related question is about the order of the __init__ calls. Considering
the following sample:

#--8<---
class A (object):
def __init__ (self):
super (A, self) .__init__ ()
print 'i am an A'
def foo (self):
print 'A.foo'

class B (object):
def __init__ (self):
super (B, self) .__init__ ()
print 'i am a B'
def foo (self):
print 'B.foo'

class C (A, B):
def __init__ (self):
super (C, self) .__init__ ()
print 'i am a C'

c = C ()
c.foo ()
#--8<---

aerts $ python2.4 inheritance.py
i am a B
i am an A
i am a C
A.foo

I do understand the lookup for foo: foo is provided by both classes A
and B and I do not state which one I want to use, so it takes the first
one in the list of inherited classes (order of the declaration). However
I cannot find an explanation (I may have googled the wrong keywords) for
the order of the __init__ calls from C. I was expecting (following the
same order as the method lookup):

i am an A
i am a B
i am a C
A.foo

Thanks
 
S

Scott David Daniels

rafi said:
A related question is about the order of the __init__ calls. Considering
the following sample:

#--8<---
class A (object):
def __init__ (self):
super (A, self) .__init__ ()
print 'i am an A'
class B (object):
def __init__ (self):
super (B, self) .__init__ ()
print 'i am a B'
class C (A, B):
def __init__ (self):
super (C, self) .__init__ ()
print 'i am a C'
c = C ()

aerts $ python2.4 inheritance.py
i am a B
i am an A
i am a C

I do understand the lookup for foo: foo is provided by both classes A
and B and I do not state which one I want to use, so it takes the first
one in the list of inherited classes (order of the declaration). However
I cannot find an explanation (I may have googled the wrong keywords) for
the order of the __init__ calls from C. I was expecting (following the
same order as the method lookup):

This should make it clear:
class A (object):
def __init__ (self):
print '<A>',
super (A, self) .__init__ ()
print '</A>'
class B (object):
def __init__ (self):
print '<B>',
super (B, self) .__init__ ()
print '</B>'
class C (A, B):
def __init__ (self):
print '<C>',
super (C, self) .__init__ ()
print '</C>'

C()

--Scott David Daniels
(e-mail address removed)
 
B

Bengt Richter

Hi all,

In the following code why am i not able to access class A's object attribute - 'a' ? I wishto extent class D with all the attributes of its base classes. how do i do that ?

thanks in advance for enlightment ...

here's the snippet

#!/usr/bin/python

class A(object):
def __init__(self):
self.a = 1

class B(object):
def __init__(self):
self.b = 2

class C(object):
def __init__(self):
self.c = 3

class D(B, A, C):
def __init__(self):
self.d = 4
super(D, self).__init__()

if __name__ == '__main__':
x = D()
print x.a # errs with - AttributeError

super(D, self) is going to find __init__ in the first base in the mro where it's
defined. So x.b will be defined, but not x.a.

I don't know what you are defining, but you could call the __init__ methods
of all the base classes by something like (untested)

for base in D.mro()[1:]:
if '__init__' in vars(base): base.__init__(self)

replacing your super line above in class D, but I would be leery of
using __init__ methods that way unless I had a really good rationale.

Regards,
Bengt Richter
 
K

km

Hi all,

In the following code why am i not able to access class A's object attribute - 'a' ? I wishto extent class D with all the attributes of its base classes. how do i do that ?

thanks in advance for enlightment ...

here's the snippet

#!/usr/bin/python

class A(object):
def __init__(self):
self.a = 1

class B(object):
def __init__(self):
self.b = 2

class C(object):
def __init__(self):
self.c = 3

class D(B, A, C):
def __init__(self):
self.d = 4
super(D, self).__init__()

if __name__ == '__main__':
x = D()
print x.a # errs with - AttributeError
 
K

km

Hi peter,

ya got it working :) now i understand mro better.

thanks,
KM
-------------------------------------------------------------
 
R

rafi

Scott said:
This should make it clear:
class A (object):
def __init__ (self):
print '<A>',
super (A, self) .__init__ ()
print '</A>'
class B (object):
def __init__ (self):
print '<B>',
super (B, self) .__init__ ()
print '</B>'
class C (A, B):
def __init__ (self):
print '<C>',
super (C, self) .__init__ ()
print '</C>'

C()

Gosh, based on your code I added an attribute foo on both A and B, and I
now understand... The super goes through all the super classes init to
find the attributes that may have name conflict and keep the value of
the attribute baesd upon the order of the class declaration in the
definition of C (here the value of foo in A). Am I right? I am mostly
using old style (without type unification) init but this motivate the
shift for the new style. Is there somewhere a document about this?

Thanks a lot Scott
 
M

Michele Simionato

http://fuhm.org/super-harmful/

That is a pretty good page; I must say that my position is more radical
(i.e. it is not super which
is harmful, it is multiple inheritance itself that it is harmful: was I
going to design a new language
I would implement it *without* multiple inheritance).

Michele Simionato
 
R

Reinhold Birkenfeld

Michele said:
That is a pretty good page; I must say that my position is more radical
(i.e. it is not super which
is harmful, it is multiple inheritance itself that it is harmful: was I
going to design a new language
I would implement it *without* multiple inheritance).

Multiple inheritance can be very useful if not used in an unresponsible way.

For example, think of mixins. Or compatibility layers. Lately I had to adapt
a wx 2.6 application to wx 2.4 I could either search and substitute $BIGNUM
self.Bind() calls (which isn't done via simple Emacs magic, cause the replacement
varies), or I could write a compatibility mixin and derive every GUI class from
it, too.

Reinhold
 
S

Sion Arrowsmith

That way lies Java. The number of times I've wished an interface
were actually a mixin.... *shudder*
Multiple inheritance can be very useful if not used in an unresponsible way.

Exactly. I think the correct approach is to regard multiple
inheritence as a very advanced OO topic, leave it out of tutorials as
much as possible, and when finally introduced reinforce the idea that
it should be used only with caution. Speaking as someone who has used
it to commit monstrosities in C++ which I have grown to regret.
 
R

rafi

Michele said:
That is a pretty good page; I must say that my position is more radical
(i.e. it is not super which
is harmful, it is multiple inheritance itself that it is harmful: was I
going to design a new language
I would implement it *without* multiple inheritance).

Michele Simionato

I do not agree on that point: Nobody is forced to used multiple
inheritance, and when it is the right solution to be used, then it would
be a shame not to have it. I remember the pain it was to implement some
CORBA stuff using Java (moreover compared to C++) because of the lack of
multiple inheritance.
 
M

Michele Simionato

Sion Arrowsmith
That way lies Java

well, no, a dynamic language such as Python with the possibility of
adding methods on the fly and metaclasses could live pretty well
without
multiple inheritance. There would be no real loss
of power and hopefully less monstruosities such
a Zope 2. But maybe this is just wishful thinking ...

Michele Simionato
 
M

Mike Meyer

Michele Simionato said:
adding methods on the fly and metaclasses could live pretty well
without
multiple inheritance. There would be no real loss
of power and hopefully less monstruosities such
a Zope 2. But maybe this is just wishful thinking ...

Um, no real loss of power? Well, in the sense that all languages are
turing-equivalent, maybe.

My current project includes a small set of classes that all deal with
web pages. The classes exist in three layers: the first layer is very
abstract, and provides a general mechanism. The second layer adapts
the general mechanasm to a specific case. The last layer provides
application-specific functionality. The classes intercommunicate, but
are generally completely unrelated to each other except for the more
concrete classes inheriting from the layer above.

So far, so good - it's all simple single inheritance.

Now, I have a class Utility that collects utility methods that are
useful for dealing with web pages: extracting data, filling out forms,
etc. These are provided as a mixin. The classes that need this
functionality inherits from it as well as their parent. The classes
that don't need it don't. This makes use of multiple inheritance.

Without multiple inheritance, I would have had to make the Utility
class a parent of all the most abstract classes. Some of the those
classes don't need that functionality - but their children do, so they
have to inherit from it. Children's needs shouldn't influence the
implementation of the child - that's simply ugly. Also, it creates an
apparent relationship between all the most abstract classes that
doesn't really exist.

Do you have a proposed solution that doesn't have these problems?

<mike
 
M

Michele Simionato

If I understand correcly you have a situation like this:

Base

|

Parent1 Mixin
| |
| |
Children1

Base

|

Parent2 Mixin
| |
| |
Children2


Base

|

Parent3
|
|
Children3

The Base class is pretty general, Parent1, Parent2 and Parent3 are more
specific, Children1 and Children2 requires the Mixin class, but
Children3 does
not require it.

Let me note that this looks like a sensible design and that I agree
that in simple
situations multiple inheritance could be the simplest solution.
Nevertheless 1)
I am scared of the case where you have hundreds of methods coming from
everywhere (ex. Zope) and 2) even in simple situations a solution
without
multiple inheritance is not that much worse.

Various solutions (using pseudocode):

1. use single inheritance and attach the mixin methods by hand:

class Children2(Parent2): pass

for methodname, method in methods_of(Mixin):
setattr(Children2, methodname, method)

if you think this is ugly, use a metaclass to attach the methods for
you. This is probably still ugly, since it is akin to reimplementing
multiple inheritance by hand. Still, it can be done, if you really
want.

2. use single inheritance and delegation. If "mixin" is a proxy to
the methods in the mixin (for instance implemented as an attribute
descriptor) you could do

class Children2(Parent2):
mixin = Proxy(Mixin)

c2 = Children2()

and then c2.mixin.method(args) would actually call Mixin.method(c2,
args).
I like this solution since it is clear where methods come from and
it scales
better to complex situations (still if you have only 2 or 3 methods
multiple inheritance could be pretty fine).

3. think differently and use multimethods

There are implementations of multimethods in Python (for instance in
PEAK).
This example looks like a good candidate for a multiple dispatch
solution.
You would use single inheritance and promote the mixin methods to
multimethods. BTW, I think multimethods are pretty
nifty and I would welcome them in standard Python.



Michele Simionato
 
M

Mike Meyer

I think you're replying to me, but you didn't include any indication
so I can't be sure.
If I understand correcly you have a situation like this:

Base

|

Parent1 Mixin
| |
| |
Children1

Base

|

Parent2 Mixin
| |
| |
Children2


Base

|

Parent3
|
|
Children3

Mostly right. What missing from the diagram is that there are three
Base classes: Base1, Base2 and Base3. They have no methods in
common.
The Base class is pretty general, Parent1, Parent2 and Parent3 are more
specific, Children1 and Children2 requires the Mixin class, but
Children3 does
not require it.

At least one ParentX also uses Mixin.
Let me note that this looks like a sensible design and that I agree
that in simple
situations multiple inheritance could be the simplest solution.

Thank you.
Nevertheless 1) I am scared of the case where you have hundreds of
methods coming from everywhere (ex. Zope) and

Any tool can be abused.
Various solutions (using pseudocode):
1. use single inheritance and attach the mixin methods by hand:
2. use single inheritance and delegation. If "mixin" is a proxy to
the methods in the mixin (for instance implemented as an attribute
descriptor) you could do

These two are cases of what I was talking about when I referred to the
Church-Turing thesis. Also, I don't see how they make the situation
you are scared of above any better.
3. think differently and use multimethods

There are implementations of multimethods in Python (for instance in
PEAK).
This example looks like a good candidate for a multiple dispatch
solution.
You would use single inheritance and promote the mixin methods to
multimethods.

I don't see how that would help at all. You haven't done anything
about solving the base problem - that getting the methods into my
classes cleanly needs multiple inheritance. Further, I don't need
methods that are distinguished based on their arguments - they all
take a fixed set of arguments, and operate on them and the state of
the instance. None seem to be candidates for being multimethods. The
mixin methods tend to provide general functionality, and get used in
radically different places by the different child classes.

You did miss the one alternative I considered: making the methods of
Mixin stand-alone functions, and passing them extra arguments instead
of using attributes of the instance. They would all then look like
mixin_func(self.foo, self.bar, var, value). I decided that this wasn't
as readable as inherting the methods.
BTW, I think multimethods are pretty nifty and I would welcome them
in standard Python.

I wouldn't bet on it happening. They seem to violate "explicit is
better than implicit".

<mike
 
M

Michele Simionato

Mike Meyer:
I think you're replying to me, but you didn't include any indication
so I can't be sure.

Oops, sorry, yes, I was replying to you.
These two are cases of what I was talking about when I referred to the
Church-Turing thesis.

Well, let me put it in this way. If a language can implement a
missing feature easily, then you are not really missing a big thing.
And the feature may not be provided by default for sake of semplicity
and/or uniformity of style. For instance Python does not have
repeat-until
loops, case statement, ternary operator, etc. (obviously I am not
advocating to remove multiple inheritance now, I am justing
speculating, talking about an hypotetic new Python-like language).
Also, I don't see how they make the situation
you are scared of above any better.

It would discourage some people from some abuses, in the same sense the
absence of repeat-until, case statemente, ternary operator etc are
working right now.
I don't see how that would help at all. You haven't done anything
about solving the base problem - that getting the methods into my
classes cleanly needs multiple inheritance. Further, I don't need
methods that are distinguished based on their arguments - they all
take a fixed set of arguments, and operate on them and the state of
the instance. None seem to be candidates for being multimethods. The
mixin methods tend to provide general functionality, and get used in
radically different places by the different child classes.

You did miss the one alternative I considered: making the methods of
Mixin stand-alone functions, and passing them extra arguments instead
of using attributes of the instance. They would all then look like
mixin_func(self.foo, self.bar, var, value). I decided that this wasn't
as readable as inherting the methods.


Uhm? I do not follow you. Multimethods would dispatch according
to the type and would act differently on the childrens, dependending
on their state. Perhaps I would need more information to understand
what
you have in mind.

But at the end my point is "I would not feel much more constrained
in expressivity if I did not have multiple inheritance in Python,
and actually I have found out that the more I use OOP, the less I
use inheritance".

Just curious if others had a similar experience.

Michele Simionato
 
M

Mike Meyer

Michele Simionato said:
Mike Meyer:

Oops, sorry, yes, I was replying to you.


Well, let me put it in this way. If a language can implement a
missing feature easily, then you are not really missing a big thing.
And the feature may not be provided by default for sake of semplicity
and/or uniformity of style. For instance Python does not have
repeat-until
loops, case statement, ternary operator, etc. (obviously I am not
advocating to remove multiple inheritance now, I am justing
speculating, talking about an hypotetic new Python-like language).


It would discourage some people from some abuses, in the same sense the
absence of repeat-until, case statemente, ternary operator etc are
working right now.

These two points are working at cross purposes. If you can implement a
missing feature easily, then it doesn't do much to discourage abuses
of that feature.
Uhm? I do not follow you. Multimethods would dispatch according
to the type and would act differently on the childrens, dependending
on their state. Perhaps I would need more information to understand
what
you have in mind.

Ok, let's take a typical Mixin example. All the classes work with HTML
pages rendered as soup. Some of them only deal with one page, others
walk through multiple pages to find some specific bit of
information. Each of them stores the page it's currently working on in
the attribute page.

The get_value method of Mixin extracts a string from self.page. You
pass it a string, it invokes methods of self.page to locate a string
that stands in a fixed relation to the string you passed in to it, and
returns the found string.

I don't see how this could be made a multimethod. What it does doesn't
change depending on selfs type. This example could trivially have been
done as a standalone function, as it only uses one attribute. Others
use more, say filling out forms based on a dictionary attribute, or
some such.
But at the end my point is "I would not feel much more constrained
in expressivity if I did not have multiple inheritance in Python,
and actually I have found out that the more I use OOP, the less I
use inheritance".

Just curious if others had a similar experience.

No, and yes. I think that using less inheritance as you get more
practice with it is a common thing. At first, it seems very cool, and
you're tempted to use it for everything. Then you find the problems
that this creates, and back off from it some. On the other hand, as my
understanding of inheritance deepened, I found myself using multiple
inheritance more, not less. Mostly, it's for mixins. Sometimes, I
really do need objects that have multiple types.

<mike
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,014
Latest member
BiancaFix3

Latest Threads

Top