0

I am trying to write a plugin environment where I need to do multiple inheritances on an unknown number of classes. Therefore, I have opted to use the type class creation:

class A(object):
   def __init__(self,s):
      self.a="a"
   def testA(self,x):
      print(x)

class B(object):
   def __init__(self,s):
      self.b="b"
   def testA(self,x):
      print(x)

C = type('C', (A,B), {})

x= C("test")
print x.b

When I run the above code, I get the error:

AttributeError: 'C' object has no attribute 'b'

This is because only the init for class A is being run when the instance for class C is initialized. My question is how can I get the class C to have both the init for class A as well as the init for class B to run when an instance of class C is initialized. I do realize that if I had class C like the following it would work:

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

However, given that I need to have a dynamic list of classes inherited this will not work.

1
  • 5
    Use super(), which is intended for exactly this scenario. Commented Apr 20, 2018 at 17:08

1 Answer 1

2

It seems you're using python 2 so I'm using this old python 2 super() syntax where you have to specify the class and the instance, although it would work in python 3 as well. In python 3 you could also use the shorter super() form without parameters.

For multiple inheritance to work is important that the grandparent class __init__ signature matches the signature of all siblings for that method. To do that, define a common parent class (MyParent in this example) whose __init__ has the same parameter list as all the childs. It will take care of calling the object's __init__ that doesn't take any parameter, for us.

from __future__ import print_function

class MyParent(object):
    def __init__(self, s):
        super(MyParent, self).__init__()

class A(MyParent):
    def __init__(self, s):
        self.a = "a"
        super(A, self).__init__(s)
    def testA(self, x):
        print(x)

class B(MyParent):
    def __init__(self, s):
        self.b = "b"
        super(B, self).__init__(s)

    def testA(self,x):
        print(x)

C = type('C', (A, B), {})

x = C("test")
print(x.b)

You can define as many children to MyParent as you want, and then all __init__ methods will be called, provided you used super() correctly.

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you for your answer. Could you tell my why there is a super in the init of MyParent?
it calls object.__init__... which does nothing, but you shouldn't rely on it doing nothing. It is the initialization of the parent class, so you should always call it

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.