How to call Base Class's __init__ method from the child class? [duplicate]
Asked Answered
L

4

156

If I have a python class as:

class BaseClass(object):
#code and the init function of the base class

And then I define a child class such as:

class ChildClass(BaseClass):
#here I want to call the init function of the base class

If the init function of the base class takes some arguments that I am taking them as arguments of the child class's init function, how do I pass these arguments to the base class?

The code that I have written is:

class Car(object):
    condition = "new"

    def __init__(self, model, color, mpg):
        self.model = model
        self.color = color
        self.mpg   = mpg

class ElectricCar(Car):
    def __init__(self, battery_type, model, color, mpg):
        self.battery_type=battery_type
        super(ElectricCar, self).__init__(model, color, mpg)

Where am I going wrong?

Louls answered 6/10, 2013 at 6:1 Comment(4)
Your format is wrong, is that a copy-and-paste problem? Python will bark on wrong format.Baumgartner
@Baumgartner format is wrong? You mean indentation or am I missing something else here?Louls
Yea.. I mean indentation. Please look at my answer below.Baumgartner
don't use derived class name do this in python 3 (pseudocode): super().__init__(args...)Scheelite
B
185

You could use super(ChildClass, self).__init__()

class BaseClass(object):
    def __init__(self, *args, **kwargs):
        pass

class ChildClass(BaseClass):
    def __init__(self, *args, **kwargs):
        super(ChildClass, self).__init__(*args, **kwargs)

Your indentation is incorrect, here's the modified code:

class Car(object):
    condition = "new"

    def __init__(self, model, color, mpg):
        self.model = model
        self.color = color
        self.mpg   = mpg

class ElectricCar(Car):
    def __init__(self, battery_type, model, color, mpg):
        self.battery_type=battery_type
        super(ElectricCar, self).__init__(model, color, mpg)

car = ElectricCar('battery', 'ford', 'golden', 10)
print car.__dict__

Here's the output:

{'color': 'golden', 'mpg': 10, 'model': 'ford', 'battery_type': 'battery'}
Baumgartner answered 6/10, 2013 at 6:6 Comment(5)
If you pass BaseClass to super, it'll skip over BaseClass and call object.__init__, which is almost certainly not what you want.Pangaro
Meanwhile, the only thing wrong with the OP's code is his indentation, explaining super (even if you explained it correctly, which you didn't) doesn't help, especially given that he already used it exactly the same way; in fact, it's character-for-character identical.Pangaro
Thanks, @abarnert. Initially, he did not post his code and the question he asked is the one in the title.Baumgartner
Your answer is the most highly voted. You should really reference how to not use the derived class name by doing super().__init__(args)Scheelite
@CharlieParker can you please expand? What should we not do?Misestimate
G
90

As Mingyu pointed out, there is a problem in formatting. Other than that, I would strongly recommend not using the Derived class's name while calling super() since it makes your code inflexible (code maintenance and inheritance issues). In Python 3, Use super().__init__ instead. Here is the code after incorporating these changes :

class Car(object):
    condition = "new"

    def __init__(self, model, color, mpg):
        self.model = model
        self.color = color
        self.mpg   = mpg

class ElectricCar(Car):

    def __init__(self, battery_type, model, color, mpg):
        self.battery_type=battery_type
        super().__init__(model, color, mpg)

Thanks to Erwin Mayer for pointing out the issue in using __class__ with super()

Glaudia answered 2/1, 2015 at 10:17 Comment(4)
Can you give any explanation for the recommendation 'not to use the Derived class's name'?Claudetta
@Claudetta I updated the answer to explain why class is a better choice.Newsmonger
@CraigFinch it doesn't seem to be a good idea at all to use self.__class__. In Python 3 you can simply use super().__init__Hertzog
Yet another reason Py3 is superior to Py2. (As someone who came to python after 3.4 came out)Luciano
H
19

If you are using Python 3, it is recommended to simply call super() without any argument:

class Car(object):
    condition = "new"

    def __init__(self, model, color, mpg):
        self.model = model
        self.color = color
        self.mpg   = mpg

class ElectricCar(Car):
    def __init__(self, battery_type, model, color, mpg):
        self.battery_type=battery_type
        super().__init__(model, color, mpg)

car = ElectricCar('battery', 'ford', 'golden', 10)
print car.__dict__

Do not call super with class as it may lead to infinite recursion exceptions as per this answer.

Hertzog answered 12/2, 2016 at 7:36 Comment(2)
Just curious why all the answers in this question are setting self.battery_type before calling the super init method. Isn't it considered better practice to call super init before modifying anything in the object, so the base class is fully initialized first? Or am I missing something here?Feeder
@Feeder Most likely because it was that way in the OP's question. I would agree that the reverse is usually better.Ehrlich
S
15

You can call the super class's constructor like this

class A(object):
    def __init__(self, number):
        print "parent", number

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

b = B()

NOTE:

This will work only when the parent class inherits object

Sandstorm answered 6/10, 2013 at 6:6 Comment(1)
don't use derived class name do this in python 3 (pseudocode): super().__init__(args...)Scheelite

© 2022 - 2024 — McMap. All rights reserved.