That is correct. Note that you can also call the __init__ method directly on the Base class, like so:
class Child(Base):
def __init__(self, something_else):
Base.__init__(self, value = 20)
self.something_else = something_else
That's the way I generally do it. But it's discouraged, because it doesn't behave very well in the presence of multiple inheritance. Of course, multiple inheritance has all sorts of odd effects of its own, and so I avoid it like the plague.
In general, if the classes you're inheriting from use super, you need to as well.
That is correct. Note that you can also call the __init__ method directly on the Base class, like so:
class Child(Base):
def __init__(self, something_else):
Base.__init__(self, value = 20)
self.something_else = something_else
That's the way I generally do it. But it's discouraged, because it doesn't behave very well in the presence of multiple inheritance. Of course, multiple inheritance has all sorts of odd effects of its own, and so I avoid it like the plague.
In general, if the classes you're inheriting from use super, you need to as well.
If you're using Python 3.1, super is new and improved. It figures out the class and instance arguments for you. So you should call super without arguments:
class Child(Base):
def __init__(self, value, something_else):
super().__init__(value)
self.something_else = something_else
...
Videos
In line with the other answers, there are multiple ways to call super class methods (including the constructor), however in Python 3 the process has been simplified:
Python 3
class A(object):
def __init__(self):
print("world")
class B(A):
def __init__(self):
print("hello")
super().__init__()
Python 2
In Python 2, you have to call the slightly more verbose version super(<containing classname>, self), which is equivalent to super()as per the docs.
class A(object):
def __init__(self):
print "world"
class B(A):
def __init__(self):
print "hello"
super(B, self).__init__()
super() returns a parent-like object in new-style classes:
class A(object):
def __init__(self):
print("world")
class B(A):
def __init__(self):
print("hello")
super(B, self).__init__()
B()
is the sole purpose of doing that is to just ensure that the base class is initialized?
Well yes, but what do you mean, just?
Assuming your base class has a reason to exist, it must do something.
Unless it's just a convenient collection of @staticmethod functions, whatever it does might depend on its __init__ having been called, because that's how class objects work.
Even if your base class has an empty __init__ today, it's sensible to call it, in case that changes in the future.
Or, would there be other possible use cases?
The use case is to make sure that the base class part of your object is correctly initialized. Without that, you can't safely call any of its non-static methods.
In principle your base class could do something tricksy in its __init__ (starting a background thread, or registering the instance with some singleton, or ... whatever). So yes, there could be effects other than just assigning instance variables, but this is still part of initializing an object of that base class.
In C++ or Java, the compiler will require you to call the base class constructor (either by automatically inserting a zero-argument call or by giving you an error).
Python requires you to call it yourself, as it is written:
If a base class has an
__init__()method, the derived class’s__init__()method, if any, must explicitly call it to ensure proper initialization of the base class part of the instance
The reason why is a principle of object oriented design. An A "is-a" Base, which could also be written equivalently as an A "has-a" Base. Unless you specifically want to interfere with the implementation of Base, you have to allow the object to be initialized as designed. Skipping the constructor will leave the Base object improperly initialized, disappointing anyone who expects it to behave as a Base object ought to.
When overriding a method besides the constructor, it is the programmer's discretion to delegate to the base class implementation or to override it entirely. This can still lead to incorrect behavior --- several API docs I can think of pepper the documentation with "If you override this method, you should call super" for various methods.
Does python call by default the base class constructor's when running the derived class' one? Do I have to implicitly do it inside the derived class constructor?
No and yes.
This is consistent with the way Python handles other overridden methods - you have to explicitly call any method from the base class that's been overridden if you want that functionality to be used in the inherited class.
Your constructor should look something like this:
def __init__(self, numberOfInputs, numberOfHiddenNeurons, numberOfOutputs):
NeuralNetworkBase.__init__(self, numberOfInputers, numberOfHiddenNeurons, numberOfOutputs)
self.outputLayerDeltas = numpy.zeros(shape = (numberOfOutputs))
self.hiddenLayerDeltas = numpy.zeros(shape = (numberOfHiddenNeurons))
Alternatively, you could use Python's super function to achieve the same thing, but you need to be careful when using it.
You will have to put this in the __init__() method of NeuralNetworkBackPropagation, that is to call the __init__() method of the parent class (NeuralNetworkBase):
NeuralNetworkBase.__init__(self, numberOfInputs, numberOfHiddenNeurons, numberOfOutputs)
The constructor of the parent class is always called automatically unless you overwrite it in the child class. If you overwrite it in the child class and want to call the parent's class constructor as well, then you'll have to do it as I showed above.