title: Reason for calling super class constructor using superclass.__init()__ instead of superclass()
body: <p>I am a beginner in Python and using Lutz's book to understand OOPS in Python. This question might be basic, but I'd appreciate any help. I researched SO and found answers on "how", but not "why."</p>
  
  <p>As I understand from the book, if <code>Sub</code> inherits <code>Super</code> then one need not call superclass' (<code>Super</code>'s) <code>__init__()</code> method.</p>
  
  <p><strong>Example:</strong></p>
  
  <pre><code>class Super:
      def __init__(self,name):
          self.name=name
          print("Name is:",name)
  
  class Sub(Super):
      pass
  
  a = Sub("Harry")
  a.name
  </code></pre>
  
  <p>Above code does assign attribute <code>name</code> to the object <code>a</code>. It also prints the <code>name</code> as expected. </p>
  
  <p>However, if I modify the code as:</p>
  
  <pre><code>class Super:
      def __init__(self,name):
          print("Inside Super __init__")
          self.name=name
          print("Name is:",name)
  
  class Sub(Super):
        def __init__(self,name):
            Super(name) #Call __init__ directly
  
  a = Sub("Harry")
  a.name
  </code></pre>
  
  <p>The above code doesn't work fine. By fine, I mean that although <code>Super.__init__()</code> does get called (as seen from the print statements), there is no attribute attached to <code>a</code>. When I run <code>a.name</code>, I get an error, <code>AttributeError: 'Sub' object has no attribute 'name'</code></p>
  
  <p>I researched this topic on SO, and found the fix on <a href="https://stackoverflow.com/questions/904036/chain-calling-parent-constructors-in-python?noredirect=1&amp;lq=1">Chain-calling parent constructors in python</a> and <a href="https://stackoverflow.com/questions/3782827/why-arent-superclass-init-methods-automatically-invoked">Why aren&#39;t superclass __init__ methods automatically invoked?</a></p>
  
  <p>These two threads talk about how to fix it, but they don't provide a reason for why. </p>
  
  <p>Question: <strong>Why</strong> do I need to call <code>Super</code>'s <code>__init__</code> using <code>Super.__init__(self, name)</code> OR <code>super(Sub, self).__init__(name)</code> instead of a direct call <code>Super(name)</code>? </p>
  
  <p>In <code>Super.__init__(self, name)</code> and  <code>Super(name)</code>, we see that Super's <code>__init__()</code> gets called, (as seen from print statements), but only in <code>Super.__init__(self, name)</code> we see that the attribute gets attached to <code>Sub</code> class.</p>
  
  <p>Wouldn't <code>Super(name)</code> automatically pass <code>self</code> (child) object to <code>Super</code>? Now, you might ask that how do I know that <code>self</code> is automatically passed? If I modify <code>Super(name)</code> to <code>Super(self,name)</code>, I get an error message that <code>TypeError: __init__() takes 2 positional arguments but 3 were given</code>. As I understand from the book, <code>self</code> is automatically passed. So, effectively, we end up passing <code>self</code> twice. </p>
  
  <p>I don't know why <code>Super(name)</code> doesn't attach <code>name</code> attribute to <code>Sub</code> even though <code>Super.__init__()</code> is run. I'd appreciate any help. </p>
  
  <hr>
  
  <p>For reference, here's the working version of the code based on my research from SO:</p>
  
  <pre><code>class Super:
      def __init__(self,name):
          print("Inside __init__")
          self.name=name
          print("Name is:",name)
  
  class Sub(Super):
      def __init__(self,name):
          #Super.__init__(self, name) #One way to fix this
          super(Sub, self).__init__(name) #Another way to fix  this
  
  a = Sub("Harry")
  a.name
  </code></pre>
  
  <p>PS: I am using <code>Python-3.6.5</code> under Anaconda Distribution.</p>