Jump to content
  • Advertisement

Archived

This topic is now archived and is closed to further replies.

civguy

How to do diamond-shaped multiple inheritance in Python?

This topic is 5734 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I tried this:
class Base:
	def __init__(self):
		print 'base'

class D1(Base):
	def __init__(self):
		Base.__init__(self)
		print 'd1'

class D2(Base):
	def __init__(self):
		Base.__init__(self)
		print 'd2'

class Bottom(D1, D2):
	def __init__(self):
		D1.__init__(self)
		D2.__init__(self)
		print 'bottom'
     
But creating a Bottom-object will call the base class constructor twice (well, naturally..). How can I make it so that I can construct D1, D2 and Bottom, and every time Base constructor is called once and only once? And when Bottom is created, both D1 and D2 constructors get called too. I can think of several very kludgy ways of doing this (like adding a counter to Base class that prevents it's constructor being called twice. Or passing a new parameter to D2 constructor so that it won't call the Base constructor). But there's gotta be an elegant way. This whole explicit constructor calling bugs me greatly, since I can't think of a case when I don't want the base class constructor to be called. But it's what Dive Into Python used too so I suppose it's the right way to do it.. [edited by - civguy on April 2, 2003 3:32:00 AM]

Share this post


Link to post
Share on other sites
Advertisement
Cursed, I think I searched with too many keywords since I didn''t find anything relevant . But thanks a lot for the link, I think it''s what I wanted (gotta test it first).

Share this post


Link to post
Share on other sites
self.__class__ wasn''t so fun after all. When the super class constructors D1.__init__ and D2.__init__ are called, self.__class__ is still the same, so it won''t reach the top-most Base constructor :/

Anyway, I managed to do this now:

class Base:
def __init__(self):
print ''base''

class D1(Base):
def __init__(self, word, **any):
initAll(self, D1)
print ''d1 with'', word, ''and'', any

class D2(Base):
def __init__(self, num):
initAll(self, D2)
print ''d2'', num

class Bottom(D1, D2):
def __init__(self):
initAll(self, Bottom,
{D1: "''bleh'', g = 3",
D2: "3"}) # give arguments to constructors
print ''bottom''

With initAll defined like this:

def initAll(self, type, params = {}):
"""Loop on all base classes, and invoke their constructors.
Protect against diamond inheritance."""

# Create a dictionary that tells
# what constructors have been visited
if self.__class__ is type:
self.__initdic__ = {}

for base in type.__bases__:
# Avoid problems with diamond inheritance.
basekey = str(base)
if not base in self.__initdic__:
self.__initdic__[base] = None
else:
continue

# Call this base class'' constructor if it has one.
if hasattr(base, "__init__"):
if base in params:
eval(''base.__init__(self, '' + params[base] + '')'')
else:
base.__init__(self)

# Clean up all traces
if self.__class__ is type:
del self.__initdic__

I can''t say I''m too satisfied with Python''s way of handling this.. Unless I''m still doing something horribly wrong. The initAll()-calls look pretty nasty..

Share this post


Link to post
Share on other sites
quote:
Original post by civguy
self.__class__ wasn''t so fun after all. When the super class constructors D1.__init__ and D2.__init__ are called, self.__class__ is still the same, so it won''t reach the top-most Base constructor :/

You''re supposed to do it recursively, eliminating duplicates. It still works because Python does breadth first LTR searches in base class dictionaries anyway. I think that''s what the example I linked to did; I didn''t pay too much attention to it because I hardly find MI necessary even in C++. Sorry if I wasn''t too much help.

Share this post


Link to post
Share on other sites

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!