Multiple inheritance: Interface problem workaround, please comment this

Discussion in 'Python' started by Axel Straschil, Apr 7, 2005.

  1. Hello!

    I'm working on an HTML/Cgi widget's class where multiple inheritance
    well be sometime a great thing.

    I solved all my problems for pythons multiple inheritance with this ng,
    thaks to all again, but there is one think I still dislike:

    class A(object):
    def __init__(self, a=None, **__eat):
    print "A"
    super(A, self).__init__()
    class B(object):

    def __init__(self, b=None, **__eat):
    print "B"
    super(B, self).__init__()

    class AB(A, B):
    def __init__(self, a=None, b=None):
    super(AB, self).__init__(a=a, b=b)

    ab = AB()

    This looks (and I think is) correct, but I realy dislike the **__eat
    stuff. As in python everything is virtual, I found no better solution to
    do that. In my real world, i've got constucts like:
    class A(object)
    class B(A)
    class AB(A,B)
    (not realy so ugly like that ;-), just to say I can work only with super to
    call __init__).

    My problem: If you make a coding mistake, and the mistake does not give
    a runtime error becouse **__eat is a hungry evil beast, it would be very
    hard to debug ... think of a wrong written parameter!

    So, here is my workaround, please comment this, if someone has a better
    solution I would be glad:

    class A(object):
    def __init__(self, a=None, _do_eat=False, **__eat):
    if __eat and not _do_eat: raise "I'm not hungry"
    print "A"
    super(A, self).__init__()

    class B(object):
    def __init__(self, b=None, _do_eat=False, **__eat):
    if __eat and not _do_eat: raise "I'm not hungry"
    print "B"
    super(B, self).__init__()

    class AB(A, B):
    def __init__(self, a=None, b=None):
    super(AB, self).__init__(a=a, b=b, _do_eat=True)

    ab = AB()

    Thanks,
    AXEL.
    --
    "Aber naja, ich bin eher der Forentyp." Wolfibolfi's outing in
    http://www.informatik-forum.at/showpost.php?p=206342&postcount=10
     
    Axel Straschil, Apr 7, 2005
    #1
    1. Advertising

  2. Re: Multiple inheritance: Interface problem workaround, please commentthis

    Axel Straschil wrote:
    > I solved all my problems for pythons multiple inheritance with this ng,
    > thaks to all again, but there is one think I still dislike:
    >
    > class A(object):
    > def __init__(self, a=None, **__eat):
    > print "A"
    > super(A, self).__init__()
    > class B(object):
    >
    > def __init__(self, b=None, **__eat):
    > print "B"
    > super(B, self).__init__()
    >
    > class AB(A, B):
    > def __init__(self, a=None, b=None):
    > super(AB, self).__init__(a=a, b=b)
    >
    > ab = AB()
    >

    [snip]
    >
    > My problem: If you make a coding mistake, and the mistake does not give
    > a runtime error becouse **__eat is a hungry evil beast, it would be very
    > hard to debug ... think of a wrong written parameter!


    I also agree that this style is not pretty. What are A and B in your
    real code? I would suggest that rather than this architecture, you
    might do better to either:
    (1) make A or B a mixin class that doesn't need __init__ called, or
    (2) make class AB inherit from A and delegate to B (or vice versa)
    For example:

    py> class A(object):
    .... def __init__(self, x):
    .... self.x = x
    ....
    py> class B(object):
    .... def __init__(self, y):
    .... self.y = y
    ....
    py> class C(object):
    .... def m(self):
    .... return self.x, self.y
    ....
    py> class ABC(A, C):
    .... def __init__(self, x, y):
    .... super(ABC, self).__init__(x)
    .... self._b = B(y)
    .... def __getattr__(self, name):
    .... return getattr(self._b, name)
    ....
    py> a = ABC(1, 2)
    py> a.x
    1
    py> a.y
    2
    py> a.m()
    (1, 2)

    Note that A is the "true" superclass, B is delegated to, and C is just a
    mixin class.

    STeVe
     
    Steven Bethard, Apr 7, 2005
    #2
    1. Advertising

  3. Hello!

    > (1) make A or B a mixin class that doesn't need __init__ called, or


    Would be a solution for classes that just give functionality, no
    data-structures. In that case, i would use functions, no classes ;-)

    I've seen code where there are classes without init and the hope that
    self has what they expect, not realy the blackbox oop should produce!

    > (2) make class AB inherit from A and delegate to B (or vice versa)


    As every multiple inheritance can be solved as single inheritance, if no
    better solution for my "hungry monster problem" is found, this would be
    the best way. Don't take my AB example as a real word example ;-)

    Also think of to libraries with classes which have inheritance depth
    five or more (that's what I've got). Somtimes you want to stick things
    together without knowing the inheritance tree.

    So, if there are ready class-modules, and I want to use them for
    multiple inheritance, I've to rewrite the init's of classes in the
    module!

    For me, python is the best solution in oop-webprogramming (tried perl,
    got ugly code, tried php, got php ;-), tried C++, takes too long for web
    projects). The only thing I'm dislike is the super thing with multiple
    inheritance, maby I shoud see pythons multiple inheritance as a nice to
    have and not to use thing ;-)

    Thanks,
    AXEL.
     
    Axel Straschil, Apr 8, 2005
    #3
  4. Axel:

    > So, if there are ready class-modules, and I want to use them for
    > multiple inheritance, I've to rewrite the init's of classes in the
    > module!


    Or you use a metaclass that rewrites the __init___ method for you.

    This is a start (warning: written in 5 minutes and not tested more than
    you see):

    """Given a hierarchy, makes __init__ cooperative.
    The only change needed is to add a line

    __metaclass__ = CooperativeInit

    to the base class of you hierarchy."""

    from decorate import decorate # see today thread on decorators for this

    def make_cooperative_init(cls, name, bases, dic):

    def call_cooperatively(__init__, self, *args, **kw):
    super(cls, self).__init__(*args, **kw)
    __init__(self, *args, **kw)

    __init__ = cls.__dict__.get("__init__")
    if __init__:
    cls.__init__ = decorate(__init__, call_cooperatively)

    class CooperativeInit(type):
    __init__ = make_cooperative_init

    class Base:
    __metaclass__ = CooperativeInit
    def __init__(self):
    print "B.__init__"

    class C1(Base):
    def __init__(self):
    print "C1.__init__"

    class C2(Base):
    def __init__(self):
    print "C2.__init__"

    class D(C1, C2):
    def __init__(self):
    print "D.__init__"




    D()

    # you get
    # B.__init__
    # C2.__init__
    # C1.__init__
    # D.__init__


    Michele Simionato
     
    Michele Simionato, Apr 8, 2005
    #4
  5. Axel Straschil, Apr 9, 2005
    #5
  6. Michele Simionato, Apr 9, 2005
    #6
  7. Axel Straschil, Apr 11, 2005
    #7
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Alec S.
    Replies:
    10
    Views:
    10,317
    Alec S.
    Apr 16, 2005
  2. Replies:
    7
    Views:
    679
    James Kanze
    Jul 3, 2007
  3. Daniel Pitts
    Replies:
    27
    Views:
    1,957
    Mike Schilling
    Feb 27, 2008
  4. Robert Spoons

    Inheritance request for comment

    Robert Spoons, Jan 10, 2004, in forum: Javascript
    Replies:
    5
    Views:
    135
    Robert Spoons
    Jan 12, 2004
  5. lieve again

    Multiple Inheritance vs. Interface

    lieve again, Sep 20, 2012, in forum: C++
    Replies:
    29
    Views:
    854
    Pavel
    Oct 13, 2012
Loading...

Share This Page