Python : How to "merge" two class

How about this?

class A:
    def __init__(self):
        self.a = 'a'

    def getatt(self):
        return self.a

class B:
    def __init__(self, parent) :
        self.parent = parent

    def __getattr__(self, attr):
        return getattr(self.parent, attr)

    def getattB(self):
        return self.parent.getatt()

insta = A()
instb = B(insta)

print instb.getattB()
print instb.getatt()

But method in class A can not access attr in class B.

Another way:

import functools
class A:
    def __init__(self):
        self.a = 'a'

    def getatt(self):
        return self.a

class B:
    def __init__(self, parent):
        for attr, val in parent.__dict__.iteritems():
            if attr.startswith("__"): continue
            self.__dict__[attr] = val
        for attr, val in parent.__class__.__dict__.iteritems():
            if attr.startswith("__"): continue
            if not callable(val): continue
            self.__dict__[attr] = functools.partial(val, self)

    def getattB(self):
        return self.getatt()

insta = A()
instb = B(insta)

print instb.__dict__
print instb.getattB()
print instb.getatt()

Slow with init but call fast.


The Best answer is in the comments, it was useful for me so I decided to show it in an answer (thank to sr2222): The way to dynamicaly declare inherance in Python is the type() built-in function. For my example :

class A(object) :
    def __init__(self, args):
        self.a = 'a'
        self.args = args

    def getattA(self):
        return self.a, self.args

class B(object) :
    b = 'b' 
    def __init__(self, args) :
        self.b_init = args

    def getattB(self):
        return self.b

C = type('C', (A,B), dict(c='c'))

instc = C('args')

print 'attributes :', instc.a,  instc.args, instc.b, instc.c
print 'methodes :', instc.getattA(), instc.getattB()

print instc.b_init

The code return :

attributes : a args b c
methodes : ('a', 'args') b
Traceback (most recent call last):
  File "D:\Documents and settings\Bureau\merge2.py", line 24, in <module>
    print instc.b_init
AttributeError: 'C' object has no attribute 'b_init'

My class C inerhite attributes and methods of class A and class B and we add c attribute. With the instanciation of C (instc = C('args')) The init for A is call but not for B.

Very useful for me because I have to add some attributes and methodes (the same) on different class.


I was having trouble with calling different constructors, using super doesn't necessarily make sense in a case like this, I opted to inherit and call each constructor on the current object manually:

class Foo(object):
    def __init__(self, foonum):
        super(Foo, self).__init__()
        self.foonum = foonum


class Bar(object):
    def __init__(self, barnum):
        super(Bar, self).__init__()
        self.barnum = barnum

class DiamondProblem(Foo, Bar):
    # Arg order don't matter, since we call the `__init__`'s ourself.
    def __init__(self, barnum, mynum, foonum):
        Foo.__init__(self, foonum)
        Bar.__init__(self, barnum)

        self.mynum = mynum