| Store | Cart

Calling __init__ with multiple inheritance

From: Peter Otten <__pe...@web.de>
Mon, 28 Mar 2005 21:53:04 +0200
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
 

Recent Messages in this Thread
Axel Straschil Mar 28, 2005 12:51 pm
Peter Otten Mar 28, 2005 02:08 pm
jfj Mar 29, 2005 03:27 am
Peter Otten Mar 28, 2005 05:51 pm
jfj Mar 29, 2005 04:53 am
Peter Otten Mar 28, 2005 07:53 pm
Axel Straschil Mar 29, 2005 05:53 am
Steven Bethard Mar 29, 2005 07:02 am
Peter Otten Mar 29, 2005 08:37 am
Axel Straschil Mar 29, 2005 12:21 pm
jfj Mar 29, 2005 07:38 pm
Robert Dick Mar 28, 2005 07:14 pm
phil...@yahoo.com Mar 28, 2005 04:07 pm
Messages in this thread