简体   繁体   中英

python dynamic multiple inheritance __init__

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM