129

I'm begginer of python. I can't understand inheritance and __init__().

class Num:
    def __init__(self,num):
        self.n1 = num

class Num2(Num):
    def show(self):
        print self.n1

mynumber = Num2(8)
mynumber.show()

RESULT: 8

This is OK. But I replace Num2 with

class Num2(Num):
    def __init__(self,num):
        self.n2 = num*2
    def show(self):
        print self.n1,self.n2

RESULT: Error. Num2 has no attribute "n1".

In this case, how can Num2 access n1?

Richard Hansen
  • 51,690
  • 20
  • 90
  • 97
Yugo Kamo
  • 2,349
  • 4
  • 18
  • 13

5 Answers5

191

In the first situation, Num2 is extending the class Num and since you are not redefining the special method named __init__() in Num2, it gets inherited from Num.

When a class defines an __init__() method, class instantiation automatically invokes __init__() for the newly-created class instance.

In the second situation, since you are redefining __init__() in Num2 you need to explicitly call the one in the super class (Num) if you want to extend its behavior.

class Num2(Num):
    def __init__(self,num):
        Num.__init__(self,num)
        self.n2 = num*2
Mario Duarte
  • 3,145
  • 7
  • 27
  • 37
  • 38
    Your citation isn't sufficient to explain why , when not defining a ``__init__`` method in a derived-class, it gets inherited. It is because _" if a requested attribute is not found in the class, the search proceeds to look in the base class."_ (doc) – eyquem Aug 14 '11 at 22:08
  • 7
    I'm sorry... that's basicly how inheritance works... if you inherit a class, you get the whole package, so, everything in the superclass exists in the subclass. But, if you redefine a method, it gets overriden... that's what's up in your code. – coya May 05 '17 at 19:46
  • 7
    @mario-duarte any reason why this would be better than `super(Num2, self).__init__(num)`? – gdvalderrama May 24 '18 at 17:48
  • 2
    I just switched from the solution proposed in this answer to using `super`, and my program now loads a few seconds faster. No idea why. – Guimoute Mar 27 '19 at 12:56
  • 2
    `super` is supposed to be helpful when using multiple inheritance. For single inheritance its benefits are not obvious. – Johann Bzh May 26 '20 at 12:50
  • This is the only way to make it work with old-style classes in Python 2. – Agostino Dec 22 '22 at 17:48
47

When you override the init you have also to call the init of the parent class

super(Num2, self).__init__(num)

Understanding Python super() with __init__() methods

Community
  • 1
  • 1
Mauro Rocco
  • 4,980
  • 1
  • 26
  • 40
26

A simple change in Num2 class like this:

super().__init__(num) 

It works in python3.

class Num:
        def __init__(self,num):
                self.n1 = num

class Num2(Num):
        def __init__(self,num):
                super().__init__(num)
                self.n2 = num*2
        def show(self):
                print (self.n1,self.n2)

mynumber = Num2(8)
mynumber.show()
Tom Jelen
  • 2,559
  • 1
  • 24
  • 23
Sacchit Jaiswal
  • 261
  • 3
  • 3
  • 8
    This is why I love stackoverflow. Even though this isn't the answer to the question it's helpful. Sometimes the answers people post are the answers to the question that people should have been asking. Thank you! – Glen Thompson Oct 16 '20 at 14:05
4

Since you don't call Num.__init__ , the field "n1" never gets created. Call it and then it will be there.

0

Based on this: Can I collect and merge different answers into an accepted one?

I am creating a wiki answer collecting input from above two latest answers:
Answer with code by Sacchit Jaiswal & Tom Jelen
Answer with reason or why it's needed by Mauro Rocco


When you override the init you have also to call the init of the parent class
Understanding Python super() with __init__() methods

super(Num2, self).__init__(num)

It works in python3.

class Num:
        def __init__(self,num):
                self.n1 = num

class Num2(Num):
        def __init__(self,num):
                super().__init__(num)
                self.n2 = num*2
        def show(self):
                print (self.n1,self.n2)

mynumber = Num2(8)
mynumber.show()