-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

closed as primarily opinion-based by gnat, marstato, Jörg W Mittag, BobDalgleish, Robert Harvey Jun 14 at 14:21

Many good questions generate some degree of opinion based on expert experience, but answers to this question will tend to be almost entirely based on opinions, rather than facts, references, or specific expertise. If this question can be reworded to fit the rules in the help center, please edit the question.

  • What would you expect to happen if A's constructor requires arguments that B's constructor doesn't know how to supply? – Kilian Foth Jun 14 at 6:26
  • Probably just call the default constructor, this could be the implicit action taken by the interpreter/compiler – Saurabh P Bhandari Jun 14 at 6:40
  • 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. – Kilian Foth Jun 14 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 Jun 14 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 Jun 14 at 11:22
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.

Not the answer you're looking for? Browse other questions tagged or ask your own question.