Steve
Steve

Reputation: 347

Python: "self" in inheritance

A basic question on inheritance and "self" here.

Good code with no error: (Correction: Turns out this is NOT GOOD, either. Please refer to MisterMiyagi's answers below.)

class A:
  def __init__(self, a):
    self.a = 10
    self.b = { 'a': 10, 'b': 20 }
    self.c = [ 1, 2, 3 ]

class B(A):
  def __init__(self):
    super().__init__(self)
    print(self.a)
    print(self.b)
    print(self.c)

i = B()

Bad code with errors:

class A:
  def __init__(self, a, b, c):
    self.a = 10
    self.b = { 'a': 10, 'b': 20 }
    self.c = [ 1, 2, 3 ]

class B(A):
  def __init__(self):
    super().__init__(self)
    print(self.a)
    print(self.b)
    print(self.c)

i = B()

ERROR:

Traceback (most recent call last):
  File "./o", line 16, in <module>
    i = B()
  File "./o", line 11, in __init__
    super().__init__(self)
TypeError: __init__() missing 2 required positional arguments: 'b' and 'c'

Could you please explain why it has to be:

class A:
  def __init__(self, a):

but neither

class A:
  def __init__(self):

nor

class A:
  def __init__(self, a, b, c):

?

Thank you!

Upvotes: 0

Views: 311

Answers (3)

MisterMiyagi
MisterMiyagi

Reputation: 50076

Calling a method on super() already passes on the first argument (self or cls) properly. Do not pass along self explicitly.

class A:
  def __init__(self):  # receive implicit self
    self.a = 10
    self.b = { 'a': 10, 'b': 20 }
    self.c = [ 1, 2, 3 ]

class B(A):
  def __init__(self):
    super().__init__()  # pass self implicitly
    print(self.a)
    print(self.b)
    print(self.c)

i = B()

A call such as super().__init__(self) passes self to the method twice. Thus, the method must take two parameters, e.g. def __init__(self, a). Use just super().__init__() and def __init__(self) to pass along self once instead.

Upvotes: 1

MCSH
MCSH

Reputation: 395

When you call a method on an object, the object will be assigned to the self argument of the function, for example:

class A:
  def someFunc(self):
    pass

a = A()
a.someFunc() # self == a

When you are calling the super function, your own class will be assigned to self, you should be calling super like this:

class A:
  def __init__(self, a):
    sef.a = a

class B(A):
  def __init__(self):
    a = # something
    super(self).__init__(a)
    print(self.a)

i = B()

The problem with your code is that you are assigning a to self, and then not providing a value for b and c.

Upvotes: 1

Samwise
Samwise

Reputation: 71424

A's constructor takes 3 arguments, and you're giving it 1. That's the reason for the error.

Since it doesn't use any of the 3 arguments, it should take 0 arguments, and B in turn should give it 0 arguments:

class A:
  def __init__(self):
    self.a = 10
    self.b = { 'a': 10, 'b': 20 }
    self.c = [ 1, 2, 3 ]

class B(A):
  def __init__(self):
    super().__init__()
    print(self.a)
    print(self.b)
    print(self.c)

i = B()

Upvotes: 2

Related Questions