-3

Consider the case where I have the following classes,

class A:
    def __init__(self):
        print("Class A")

class B(A):
    def __init__(self):
        print("Class B")

b = B()

The expected output with constructor inheritance is

Class A
Class B

However, the actual output is

Class B

Is this by design in python? C++ allows constructor inheritance. How does this design choice differentiate the two languages ?

Note: I agree that this can be done in python by calling the super().__init__() function, but I wanted to know the reason for this design choice. More specifically, what are the pros and cons of not using implicit constructor inheritance in python?

Question was originally asked in SO

8
  • What would you expect to happen if A's constructor requires arguments that B's constructor doesn't know how to supply? Commented Jun 14, 2019 at 6:26
  • Probably just call the default constructor, this could be the implicit action taken by the interpreter/compiler Commented Jun 14, 2019 at 6:40
  • 1
    Well, the entire point of having a constructor with mandatory arguments is to ensure that no object ever exist without some particular values. Having this condition implicitly subverted just by defining a subclass would be a bad idea. Commented Jun 14, 2019 at 6:46
  • Java doesn't have this problem either, so that's not a very strong "what if" argument. The default constructror super() is called implicitly. If the superclass doesn't have a default constructor you need to specify the constructor explicitly. If the subclass can't provide the arguments, then it can't be a subclass. This doesn't cause problems in Java, although with bad design you can end up with subclasses requiring huge parameter lists for the constructor.
    – Kayaman
    Commented Jun 14, 2019 at 6:46
  • 1
    @SaurabhPBhandari Questions regarding [programming language] design choices are, by their true nature, opinion-based. The only correct answer can usually only be given by the designers themselves. Pro/Con lists are not answers and discouraged.
    – marstato
    Commented Jun 14, 2019 at 11:22

1 Answer 1

3

In C++, constructors are special operators. There is special syntax for calling a base class constructor:

class A { ... };

class B: public A {
public:
  B() : A() { ... }
  //  ^^^^^
};

If the base constructor is not called explicitly, the default constructor for the base class will be called automatically.

This is important for C++'s memory model and data model:

  • failing to call the base constructor could lead to uninitialised memory, and would definitely lead to UB
  • classes may or may not be default constructible, which affects how explicit you need to be

Python is a very different language. It has no concept of default constructors. It has no concept of uninitialised memory. And Python constructors are just an ordinary initialization method (well, as ordinary as a dunder-method can be). There is no special syntax for calling the base class init method, it's just the same as calling any other base class method.

This kind of fits into the general Python theme of having a minimal syntax, but complex, flexible semantics. The language doesn't force you to initialize your objects properly, just as it doesn't force you to only assign specific types to some variable. As the language itself won't help you, you have to use linters to check for common mistakes.

Note that Python's flavour of multiple inheritance makes it difficult or impossible to handle "base" class constructors automatically. If the class you are writing is one of multiple bases in a multiple inheritance hierarchy, then the super().__init__() call may not go to this classes' base but possibly to an unrelated sibling class. Handling that properly requires a conscious design effort.

Of course, the best move is not to play. As a dynamic language, there are very few circumstances where inheritance is the best solution in Python.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.