parrot15
parrot15

Reputation: 329

Calling method in superclass not giving the output I expect?

I am learning about inheritance in Python and I was experimenting with superclasses and the super() function. Here is my code:

class Person:
    def __init__(self, name, age, weight):
        self.name = name
        self.age = age
        self.weight = weight

    def describe(self):
        return f"{self.name}, {self.age}, {self.weight}"


class Engineer(Person):
    def __init__(self, name, age, weight):
        super().__init__("Bla bla", 10, 100)
        self.name = name
        self.age = age
        self.weight = weight
        self.occupation = "Engineer"

    def describe(self):
        return super().describe()

my_engineer = Engineer("Larry", 17, 120)
print(my_engineer.describe())

I have a Java background, and apparently super() works differently in Python than it does in Java. In Java, the output of code equivalent to this would be Bla bla, 17, 120, but this code is outputting Larry, 17, 120. Why is this code printing out Larry, 17, 120 rather than what I expected it to? To my understanding, I am instantiating the class Engineer and passing in "Larry", 17, and 120 to __init__, but then I pass in "Bla bla", 10, and 100 to the superclass's __init__, so the superclass should be initialized with those values. Then when I call my_engineer.describe(), it should call describe() in the superclass and use the superclass's passed in values. But apparently, this is not what is happening. Can anyone explain what is going on?

Upvotes: 1

Views: 60

Answers (2)

Brad Solomon
Brad Solomon

Reputation: 40918

You're seeing the attributes being overridden. What's happening in these lines of code:

super().__init__("Bla bla", 10, 100)
self.name = name
self.age = age
self.weight = weight
self.occupation = "Engineer"
  • super().__init__("Bla bla", 10, 100) calls Person's __init__ with these values i.e. self = Person("Bla bla", 10, 100). If you stopped here, you'd have instantiated a subclass of Person and not really changed anything. (Same attributes, same method.)
  • When you then specify the next four attributes, you override what what you did in the previous line. These are set directly as the attributes of the class instance.

Essentially, that looks to Python something like:

my_engineer = Person("Bla bla", 10, 100)
my_engineer.name = "Larry"
my_engineer.age = 17
my_engineer.weight = 120
my_engineer.occupation = "Engineer"

As mentioned by @Ajax1234, it seems like you want to just get rid of those four lines altogether.

Upvotes: 3

Ajax1234
Ajax1234

Reputation: 71471

super is working correctly; however, after the super call, you override every attribute with the values passed to the child constructor. Instead, simply call super and do not initialize the child class with the same attributes:

class Engineer(Person):
   def __init__(self, *args):
      super().__init__("Bla bla", 10, 100)
   def describe(self):
      return super().describe()

my_engineer = Engineer("Larry", 17, 120)
print(my_engineer.describe())

Output:

Bla bla, 10, 100

Upvotes: 4

Related Questions