Suge
Suge

Reputation: 2897

Multiple inheritance problem in Python!

Why does c.print_a() output 'B'?

class A(object):
    def __init__(self):
        self.some_name = 'A'

    def print_a(self):
        print self.some_name

class B(object):
    def __init__(self):
        self.some_name = 'B'

    def print_b(self):
        print self.some_name

class C(A, B):
    def __init__(self):
        A.__init__(self)
        B.__init__(self)

if __name__ == '__main__':
    c = C()
    c.print_a()

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

    def print_a(self):
        print self.some_name

class B(object):
    def __init__(self, some_name='B'):
        self.some_name = some_name

    def print_b(self):
        print self.some_name

class C(A, B):
    def __init__(self):
        A.__init__(self, some_name='AAAAA')
        B.__init__(self, some_name='BBBBB')

if __name__ == '__main__':
    c = C()
    c.print_a()

Upvotes: 3

Views: 2521

Answers (3)

kriss
kriss

Reputation: 24177

Say you want C to set names for some objects of types A and B and later calling some print_a and print_b methods on objects of type C get these names back ?

You can get this type of behavior using C++ inheritance model, but python model is very different. Only one object with one set of fields. If you want the C++ behavior, the simplest way is probably to declare subobjects (and it looks like a common abuse of inheritance over composition).

Looks like you are trying to do something like below:

class Printable(object):
    def __init__(self, name):
        self.name = name

    def myprint(self):
        print self.name

class C(object):
    def __init__(self):
        self.a = Printable('A')
        self.b = Printable('B')

    def print_a(self):
        self.a.myprint()

    def print_b(self):
        self.a.myprint()

if __name__ == '__main__':
    c = C()
    c.print_a()

Upvotes: 1

Matthew Flaschen
Matthew Flaschen

Reputation: 284816

There's only one self, and you're overwriting its some_name in B.__init__. Maybe you're used to C++, where there would be two separate fields, A.some_name and B.some_name. This concept doesn't apply to Python, where attributes are created dynamically on assignment.

Upvotes: 1

Glenn Maynard
Glenn Maynard

Reputation: 57474

You only have a single object here; the some_name property is shared between methods from all inherited classes. You call A.__init__, which sets it to A, then B.__init__, which changes it to B.

Also note that you're calling base methods incorrectly; use super:

class A(object):
    def __init__(self):
        self.some_name = 'A'
        super(A, self).__init__()

    def print_a(self):
        print self.some_name

class B(object):
    def __init__(self):
        self.some_name = 'B'
        super(B, self).__init__()

    def print_b(self):
        print self.some_name

class C(A, B):
    def __init__(self):
        super(C, self).__init__()

if __name__ == '__main__':
    c = C()
    c.print_a()

Upvotes: 5

Related Questions