简体   繁体   中英

Call all __init__ but once in Python

I have a structure like

class A:
    def __init__(self, x):
        self.a=x

class B(A):
    def __init__(self, x):
        self.b=x

class C(A):
    def __init__(self, x):
        self.c=x

class D(B,C):
    def __init__(self, x):
        self.d=x

Now I'd like to extend the __init__ s such that both B and C will call A , too (B and C can be used as stand-alone classes). Moreover D should call A, B and C (D combines features from B and C but still needs to run all initializations). All __init__ take the same parameter. Obviously A should be called only once.

Do you see an easy way to do that?

Use super . As far as I'm aware, this is it's purpose ...

First, some proposed reading:

  • Super considered harmful and super (simultaneously -- by different people)

Next, an example:

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

class B(A):
    def __init__(self, x):
        print "Called B"
        super(B,self).__init__(x)
        self.b=x

class C(A):
    def __init__(self, x):
        print "Called C"
        super(C,self).__init__(x)
        self.c=x

class D(B,C):
    def __init__(self, x):
        print "Called D"
        super(D,self).__init__(x)        
        self.d=x


foo = D(10)

As stated in the comments, you often see methods which use super defined to accept any number of positional and keyword arguments:

def mymethod(self,*args,**kwargs):
    super(thisclass,self).method(*args,**kwargs)
    ...

As that allows super to pass the necessary/unnecessary arguments on to other objects in the inheritance chain. Those methods can then decide which arguments they need and ignore the rest (passing them on to the next super of course)


Finally, to complete this discussion, we need to discuss python2.x vs. python3.x. In python2.x, all of your classes must be new style (they need to inherit from object eventually). In python3.x, this is automatic. And in python3.x, you can omit the arguments to super .

 super().__init__(*args,**kwargs)

However, I prefer the python2.x style as it works for both python2.x and python3.x and I'm always left wondering how super() (python3.x style) knows what object to pass to the underlying methods as self . It seems a lot more magical then even the python2.x version to me...

Using super

class D(B, C):
    def __init__(self, *args, **kwargs):
        super(D, self).__init__(*args, **kwargs)
        self.d = args[0]

Some explanation about super here and a related question

In Python 2 you should also inherit from object to use new style classes, and add super to your other classes too.

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