472,371 Members | 1,412 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,371 software developers and data experts.

Calling __init__ with multiple inheritance

Hello!

Im working with new (object) classes and normaly call init of ther
motherclass with callin super(...), workes fine.

No, I've got a case with multiple inherance and want to ask if this is
the right and common case to call init:

class Mother(object):
def __init__(self, param_mother): print 'Mother'
class Father(object):
def __init__(self, param_father): print 'Father'
class Child(Mother, Father):
def __init__(self, param_mother, param_father):
Mother.__init__(self, param_mother)
Father.__init__(self, param_mother)
child = Child(1, 2)

Thanks, AXEL.
Jul 18 '05 #1
14 6212
Axel Straschil wrote:
Im working with new (object) classes and normaly call init of ther
motherclass with callin super(...), workes fine.

No, I've got a case with multiple inherance and want to ask if this is
the right and common case to call init:

class Mother(object):
def __init__(self, param_mother): print 'Mother'
class Father(object):
def __init__(self, param_father): print 'Father'
class Child(Mother, Father):
def __init__(self, param_mother, param_father):
Mother.__init__(self, param_mother)
Father.__init__(self, param_mother)
child = Child(1, 2)


It looks correct -- at least it /looked/ correct before tried to quote it...

Here is an alternative approach that massages the initializer signatures a
bit to work with super() in a multiple-inheritance environment:

class Mother(object):
def __init__(self, p_mother, **more):
print "Mother", p_mother, more
super(Mother, self).__init__(p_mother=p_mother, **more)

class Father(object):
def __init__(self, p_father, **more):
print "Father", p_father, more
super(Father, self).__init__(p_father=p_father, **more)

class Child(Mother, Father):
def __init__(self, p_mother, p_father, **more):
print "Child", p_father, p_mother, more
super(Child, self).__init__(p_mother=p_mother, p_father=p_father,
**more)

Child(1, 2)

Unrecognized parameters are stashed away into the <more> dictionary.

Peter

Jul 18 '05 #2
What if I want to call other methods as well? Modifying your example a
bit, I'd like the reset() method call of Child to invoke both the
Mother and Father reset() methods, without referencing them by name,
i.e., Mother.reset(self).

-------------------
class Mother(object):
def __init__(self, p_mother, **more):
print "Mother", p_mother, more
super(Mother, self).__init__(p_mother=p_mother, **more)
def reset(self):
print 'resetting Mother'

class Father(object):
def __init__(self, p_father, **more):
print "Father", p_father, more
super(Father, self).__init__(p_father=p_father, **more)
def reset(self):
print 'resetting Father'

class Child(Mother, Father):
def __init__(self, p_mother, p_father, **more):
print "Child", p_mother, p_father, more
super(Child, self).__init__(p_mother=p_mother,
p_father=p_father, **more)
def reset(self):
print 'resetting Child'

# I would like to invoke both Mother.reset()
# and Father.reset() here, but it doesn't work.
print 'trying "super"'
super(Child, self).reset()

# These next two do work, but require referencing
# Mother and Father directly.
print "calling directly"
Mother.reset(self)
Father.reset(self)

a = Child(1, 2)
a.reset()
-------------------

Thanks,
Phil

Jul 18 '05 #3
ph*****************@yahoo.com wrote:
What if I want to call other methods as well? Modifying your example a
bit, I'd like the reset() method call of Child to invoke both the
Mother and Father reset() methods, without referencing them by name,
i.e., Mother.reset(self).


[example snipped]

The problem with that aren't incompatible signatures, but the lack of an
implementation of the reset() method at the top of the diamond-shaped
inheritance graph that does _not_ call the superclass method. That method
could be basically a noop:
class Base(object):
def reset(self):
# object does something similar for __init__()
pass

class Mother(Base):
def reset(self):
print "resetting Mother"
super(Mother, self).reset()

class Father(Base):
def reset(self):
print "resetting Father"
super(Father, self).reset()

class Child(Mother, Father):
def reset(self):
print "resetting Child"
super(Child, self).reset()
Child().reset()

It might sometimes be convenient if such methods would magically spring into
existence for the object class, but for now you have to do it manually (or
perhaps someone has come up with a metaclass that I am not aware of).

Peter

PS: See http://www.python.org/2.2/descrintro.html for more on the subject.
Jul 18 '05 #4
Peter Otten wrote:

<snip>
The problem with that aren't incompatible signatures, but the lack of an implementation of the reset() method at the top of the diamond-shaped
inheritance graph that does _not_ call the superclass method. That method could be basically a noop:


<snip>

Ok, now that's cool! Up until now I've been getting along just fine
without new-style classes, but that is about to change. Thanks for the
tip!

Phil

Jul 18 '05 #5
jfj
Peter Otten wrote:

Here is an alternative approach that massages the initializer signatures a
bit to work with super() in a multiple-inheritance environment: super(Father, self).__init__(p_father=p_father, **more)

Is there any advantage using super in this case?
I think the case Father.__init__ (self, params) is simpler
and does the job perfectly well.

super seems to be needed in "Dynamic Inheritance" cases where
we don't know an object's bases and there are comlicated mro issues!
jfj

Jul 18 '05 #6
jfj wrote:
Peter Otten wrote:
Here is an alternative approach that massages the initializer signatures
a bit to work with super() in a multiple-inheritance environment:

super(Father, self).__init__(p_father=p_father, **more)

Is there any advantage using super in this case?
I think the case Father.__init__ (self, params) is simpler
and does the job perfectly well.


I agree.
super seems to be needed in "Dynamic Inheritance" cases where
we don't know an object's bases and there are comlicated mro issues!


Suppose you wanted factor out common code from the Father and Mother classes
into a Parent class -- something neither complicated nor farfetched. With
explicit calls to Parent.__init__() you would end up calling it twice from
Child.__init__(). So when you anticipate that your class hierarchy may
change, or that your classes may be subclassed by users of your library, I
think super() is somewhat less errorprone.

Peter

Jul 18 '05 #7
ph*****************@yahoo.com wrote:
What if I want to call other methods as well? Modifying your example a
bit, I'd like the reset() method call of Child to invoke both the
Mother and Father reset() methods, without referencing them by name,
i.e., Mother.reset(self).

-------------------
class Mother(object):
def __init__(self, p_mother, **more):
print "Mother", p_mother, more
super(Mother, self).__init__(p_mother=p_mother, **more)
def reset(self):
print 'resetting Mother'

class Father(object):
def __init__(self, p_father, **more):
print "Father", p_father, more
super(Father, self).__init__(p_father=p_father, **more)
def reset(self):
print 'resetting Father'

class Child(Mother, Father):
def __init__(self, p_mother, p_father, **more):
print "Child", p_mother, p_father, more
super(Child, self).__init__(p_mother=p_mother,
p_father=p_father, **more)
def reset(self):
print 'resetting Child'

# I would like to invoke both Mother.reset()
# and Father.reset() here, but it doesn't work.
print 'trying "super"'
super(Child, self).reset()

# These next two do work, but require referencing
# Mother and Father directly.
print "calling directly"
Mother.reset(self)
Father.reset(self)

a = Child(1, 2)
a.reset()
-------------------

Thanks,
Phil

if you're going to be doing a bunch of these, you could define your own variant
of the super type that calls all the methods in the mro with the given name.
Below is a minor modification to the pure-python version of built-in super that
illustrates this. There is no error-checking (e.g., if an attribute is callable
in one class, and not callable in another you will hit problems) and it's not
tested beyond what you see:

"""Hack on Super defined in http://python.org/2.2/descrintro.html
to call all super-class methods"""

class PolySuper(object):
def __init__(self, type, obj=None):
self.__type__ = type
self.__obj__ = obj
def __get__(self, obj, type=None):
if self.__obj__ is None and obj is not None:
return Super(self.__type__, obj)
else:
return self
def __getattr__(self, attr):
if isinstance(self.__obj__, self.__type__):
starttype = self.__obj__.__class__
else:
starttype = self.__obj__
mro = iter(starttype.__mro__)
for cls in mro:
if cls is self.__type__:
break
# Note: mro is an iterator, so the second loop
# picks up where the first one left off!
for cls in mro:
if attr in cls.__dict__:
x = cls.__dict__[attr]
if hasattr(x, "__get__"):
x = x.__get__(self.__obj__)

# return x
# We want all the resolved methods, in order
yield x
#raise AttributeError, attr

# Add this crude callable interface
def __call__(self, attr, *args, **kw):
methods = list(self.__getattr__(attr))
return [method(*args, **kw) for method in methods]
Then, your classes get defined like so:

class Mother(object):
def __init__(self, p_mother, **more):
print "Mother", p_mother, more
def reset(self):
print 'resetting Mother'

class Father(object):
def __init__(self, p_father, **more):
print "Father", p_father, more
def reset(self):
print 'resetting Father'

class Child(Mother, Father):
def __init__(self, p_mother, p_father, **more):
print "Child", p_mother, p_father, more
PolySuper(Child, self)("__init__", p_mother = p_mother, p_father =
p_father)
def reset(self):
print 'resetting Child'
PolySuper(Child, self)("reset")
c = Child("M1","F1") Child M1 F1 {}
Mother M1 {'p_father': 'F1'}
Father F1 {'p_mother': 'M1'} c.reset() resetting Child
resetting Mother
resetting Father


HTH
Michael

Jul 18 '05 #8
jfj
Peter Otten wrote:
jfj wrote:
Peter Otten wrote:
Here is an alternative approach that massages the initializer signatures
a bit to work with super() in a multiple-inheritance environment:

super(Father, self).__init__(p_father=p_father, **more)


Is there any advantage using super in this case?
I think the case Father.__init__ (self, params) is simpler
and does the job perfectly well.


I agree.


Ok. thanks for the confirmation.
super seems to be needed in "Dynamic Inheritance" cases where
we don't know an object's bases and there are comlicated mro issues!

Suppose you wanted factor out common code from the Father and Mother classes
into a Parent class -- something neither complicated nor farfetched. With
explicit calls to Parent.__init__() you would end up calling it twice from
Child.__init__(). So when you anticipate that your class hierarchy may
change, or that your classes may be subclassed by users of your library, I
think super() is somewhat less errorprone.


I accept the case that you avoid bugs if you extend the hierarchy
upwards. Although that's rare.

As for the case where the users of the library want to subclass, I don't
see a problem. They know they must subclass from class XXX and so they
call XXX.__init__ to construct it.

In the case of Parent diamond inheritance, super() can avoid calling
the __init__ of parent twice? How?
jfj

Jul 18 '05 #9
jfj wrote:
As for the case where the users of the library want to subclass, I don't
see a problem.**They*know*they*must*subclass*from*class* XXX*and*so*they
call XXX.__init__ to construct it.
I was thinking of

class Child(Father, Mother):
pass

where Father and Mother have a common base class Parent. That would be
initialized twice:
class Parent(object): .... def __init__(self):
.... print "parent"
.... class Father(Parent): .... def __init__(self):
.... print "father"
.... Parent.__init__(self)
.... class Mother(Parent): .... def __init__(self):
.... print "mother"
.... Parent.__init__(self)
.... class Child(Father, Mother): .... def __init__(self):
.... print "child"
.... Father.__init__(self)
.... Mother.__init__(self)
.... Father() father
parent
<__main__.Father object at 0x402ad66c> Mother() mother
parent
<__main__.Mother object at 0x402ad38c> Child() child
father
parent
mother
parent # <-- the culprit: parent initialized a second time
<__main__.Child object at 0x402ad66c>

You have several options now:
- Write __init__() in such a way that calling it twice does no harm
- Ensure that it is only called once by adding a self.initialized flag
- Document that a user class may not inherit from both Father and Mother
but the best is IMO
- let super() do the work
In the case of Parent diamond inheritance, super() can avoid calling
the __init__ of parent twice?**How?


That's the best part -- it's automatic:
class Parent(object): .... def __init__(self):
.... print "parent"
.... super(Parent, self).__init__()
.... class Father(Parent): .... def __init__(self):
.... print "father"
.... super(Father, self).__init__()
.... class Mother(Parent): .... def __init__(self):
.... print "mother"
.... super(Mother, self).__init__()
.... class Child(Father, Mother): .... def __init__(self):
.... print "child"
.... super(Child, self).__init__()
.... Father() father
parent
<__main__.Father object at 0x402ad38c> Mother() mother
parent
<__main__.Mother object at 0x402ad3cc> Child()

child
father
mother
parent # <-- parent only once
<__main__.Child object at 0x402ad38c>

That was a lot of dull code -- but you asked :-)
Seriously, I think super() scales better in a scenario with multiple
inheritance, though I won't start a holy war about the issue.

Peter
Jul 18 '05 #10
Hello!

Thanks to all for the very interesting postings!

I came to the following:

For single inheritance, super is a nice tool if you will recfactoring
the class later.

For multiple inheritance, if you want to use super, you have to have
very much knowledge of the classes you inheritance. For me, OOP is to
not have to have the deep inner knowledge of the classes I inheritance
from.

Also, for multiple inheritance, if think
Mother1.__init__(self, ...)
Mother2.__init__(self, ...)
Mother3.__init__(self, ...)
would be more clear to read then
super(MyClass).__init__(Maby this will do some magic thing)

Also, I realy dislike
__init__(self, param, **eat_some_needless_stuff)

If I later extend my class and also add some parameters to __init__,
what will happen to the classes using the baseclass?

Also, lool at that:
class Mother(object):
def __init__(self, param_mother='optional', **eat):
print 'Mother'
class Father(object):
def __init__(self, param_father='optional', **eat):
print 'Father'
class Child(Mother, Father):
def __init__(self, **ham):
super(Child, self).__init__(**ham)
child = Child(param_mother=1, param_father=1)

Father's init will not be called.

Thanks,
AXEL.
--
"Aber naja, ich bin eher der Forentyp." Wolfibolfi's outing in
http://www.informatik-forum.at/showp...2&postcount=10
Jul 18 '05 #11
Axel Straschil wrote:
I came to the following:

For single inheritance, super is a nice tool if you will recfactoring
the class later.

For multiple inheritance, if you want to use super, you have to have
very much knowledge of the classes you inheritance.


And for multiple inheritance, if you don't use super, you're likely to
call the same method twice if you ever have a diamond inheritance problem.

STeVe
Jul 18 '05 #12
Axel Straschil wrote:
Thanks to all for the very interesting postings!
You're welcome.
I came to the following:

For single inheritance, super is a nice tool if you will recfactoring
the class later.
Or if you start out with a diamond inheritance graph from the beginning.
For multiple inheritance, if you want to use super, you have to have
very much knowledge of the classes you inheritance. For me, OOP is to
not have to have the deep inner knowledge of the classes I inheritance
from.
I failed to bring my point that you need _less_ knowledge across then.
Also, for multiple inheritance, if think
Mother1.__init__(self, ...)
Mother2.__init__(self, ...)
Mother3.__init__(self, ...)
would be more clear to read then
super(MyClass).__init__(Maby this will do some magic thing)
For an advantage to show up you need at least three levels of inheritance,
see my example with the Parent class.
Also, I realy dislike
__init__(self, param, **eat_some_needless_stuff)
In turn, I really like the name you gave the dictionary parameter :-)
Normalize the initializer signature to a common set of arguments. Or pass a
single parameter and take the actual information from its attributes. Or
write a custom dispatcher, that passes only parameters that correspond to
formal arguments...
If I later extend my class and also add some parameters to __init__,
what will happen to the classes using the baseclass?

Also, lool at that:
class Mother(object):
def __init__(self, param_mother='optional', **eat):
print 'Mother'
class Father(object):
def __init__(self, param_father='optional', **eat):
print 'Father'
class Child(Mother, Father):
def __init__(self, **ham):
super(Child, self).__init__(**ham)
child = Child(param_mother=1, param_father=1)

Father's init will not be called.


Change Father/Mother.__init__() to call the superclass initializer. It may
be counterintuitive, but it works.

Peter

Jul 18 '05 #13
jfj
Peter Otten wrote:
Child()


child
father
mother
parent # <-- parent only once
<__main__.Child object at 0x402ad38c>


D-uh?

################################################
class Parent(object):
def __init__(self):
print "parent"
super(Parent, self).__init__()

class Father(Parent):
def __init__(self):
print "father"
super(Father, self).__init__()
print "D-uh"

class Mother(Parent):
def __init__(self):
print "mother"
super(Mother, self).__init__()
print "D-oh"

class Child(Father, Mother):
def __init__(self):
print "child"
super(Child, self).__init__()

Child()
################################################

This prints
child
father
mother
parent
D-oh
D-uh

Therefore super is a very intelligent function indeed!
jf
Jul 18 '05 #14
Hello!
Also, lool at that:
class Mother(object):
def __init__(self, param_mother='optional', **eat):
print 'Mother'
class Father(object):
def __init__(self, param_father='optional', **eat):
print 'Father'
class Child(Mother, Father):
def __init__(self, **ham):
super(Child, self).__init__(**ham)
child = Child(param_mother=1, param_father=1)
Father's init will not be called.

Change Father/Mother.__init__() to call the superclass initializer. It may
be counterintuitive, but it works.


OK, thanks, with the super(...).__init__() in Father/Mother it workes
and makes sense.

So, the last thing a *realy* don't like ist the
__init__(self, param, **ignore_the_rest) thing.

Anyone had troubles with that, or should I cust take this as a "python
way of thinking" ... ;-), and getting used to that?

Thanks,
AXEL.
--
"Aber naja, ich bin eher der Forentyp." Wolfibolfi's outing in
http://www.informatik-forum.at/showp...2&postcount=10
Jul 18 '05 #15

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: Graham Banks | last post by:
Does using multiple inheritance introduce any more performance overhead than single inheritance?
20
by: km | last post by:
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...
22
by: Matthew Louden | last post by:
I want to know why C# doesnt support multiple inheritance? But why we can inherit multiple interfaces instead? I know this is the rule, but I dont understand why. Can anyone give me some concrete...
5
by: Thomas Girod | last post by:
Hi. I think I'm missing something about multiple inheritance in python. I've got this code. class Foo: def __init__(self): self.x = "defined by foo" self.foo = None
60
by: Shawnk | last post by:
Some Sr. colleges and I have had an on going discussion relative to when and if C# will ever support 'true' multiple inheritance. Relevant to this, I wanted to query the C# community (the...
16
by: devicerandom | last post by:
Hi, I am currently using the Cmd module for a mixed cli+gui application. I am starting to refactor my code and it would be highly desirable if many commands could be built as simple plugins. ...
2
by: Alexander Adam | last post by:
Hi! I got a class structure similar to: class Base_Object { ... some functions ... } class Object: public Base_Object,
3
by: Jess | last post by:
Hello, I've been reading Effective C++ about multiple inheritance, but I still have a few questions. Can someone give me some help please? First, it is said that if virtual inheritance is...
13
by: stephenpas | last post by:
We are trying to monkey-patch a third-party library that mixes new and old-style classes with multiple inheritance. In so doing we have uncovered some unexpected behaviour: <quote> class Foo:...
2
by: Kemmylinns12 | last post by:
Blockchain technology has emerged as a transformative force in the business world, offering unprecedented opportunities for innovation and efficiency. While initially associated with cryptocurrencies...
0
by: Naresh1 | last post by:
What is WebLogic Admin Training? WebLogic Admin Training is a specialized program designed to equip individuals with the skills and knowledge required to effectively administer and manage Oracle...
0
hi
by: WisdomUfot | last post by:
It's an interesting question you've got about how Gmail hides the HTTP referrer when a link in an email is clicked. While I don't have the specific technical details, Gmail likely implements measures...
0
Oralloy
by: Oralloy | last post by:
Hello Folks, I am trying to hook up a CPU which I designed using SystemC to I/O pins on an FPGA. My problem (spelled failure) is with the synthesis of my design into a bitstream, not the C++...
0
BLUEPANDA
by: BLUEPANDA | last post by:
At BluePanda Dev, we're passionate about building high-quality software and sharing our knowledge with the community. That's why we've created a SaaS starter kit that's not only easy to use but also...
2
by: Ricardo de Mila | last post by:
Dear people, good afternoon... I have a form in msAccess with lots of controls and a specific routine must be triggered if the mouse_down event happens in any control. Than I need to discover what...
1
by: Johno34 | last post by:
I have this click event on my form. It speaks to a Datasheet Subform Private Sub Command260_Click() Dim r As DAO.Recordset Set r = Form_frmABCD.Form.RecordsetClone r.MoveFirst Do If...
0
by: jack2019x | last post by:
hello, Is there code or static lib for hook swapchain present? I wanna hook dxgi swapchain present for dx11 and dx9.
0
DizelArs
by: DizelArs | last post by:
Hi all) Faced with a problem, element.click() event doesn't work in Safari browser. Tried various tricks like emulating touch event through a function: let clickEvent = new Event('click', {...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.