3

I am trying to understand how inheritance works in python. I was looking at a simple code and one thing is confusing me. The code is following:

class Person:

    def __init__(self, first, last):
        self.firstname = first
        self.lastname = last

    def Name(self):
        return self.firstname + " " + self.lastname

class Employee(Person):

    def __init__(self, first, last, staffnum):
        Person.__init__(self,first, last)
        self.staffnumber = staffnum

    def GetEmployee(self):
        return self.Name() + ", " +  self.staffnumber

x = Person("Marge", "Simpson")
y = Employee("Homer", "Simpson","1007")
print(x.Name()) 
print(y.GetEmployee())

My question is that when are using Person.__init__() to call the constructor of baseclass but when we calling Name() method of base class again, instead of using "Person", we are using "self". Can somebody clear this confusion and me understand the how inheritance works in python?

4
  • 3
    That is not very Pythonic code, and is probably not the best to learn from! But note that you can use self.method to access the superclass implementation only if the subclass doesn't implement method. The subclass here implements __init__, so needs to access the superclass version explicitly (although it should do so with super), but doesn't implement Name. Try changing it and see what happens! Commented Sep 22, 2015 at 21:26
  • One more question, when we need to call a method of parent class we need to pass the child (self) as an argument. Why is that so? Commented Sep 22, 2015 at 21:48
  • Because you're not using super(Employee, self).__init__(first, last). Search for information about bound vs. unbound methods; self.Name is bound, Person.__init__ is unbound. Commented Sep 22, 2015 at 22:00
  • ok I will read up on it. Thank you! Commented Sep 22, 2015 at 22:03

3 Answers 3

2

The Employee class inherits methods from the base Person class, including the __init__ method. So at the top of the class definition, it has __init__ and Name methods.

Then the Employee class definition overwrites the __init__ method that it inherited. In order to call the __init__ method of Person, it has to call Person.__init__ by name (actually, it could use super() as another alternative).

But since Employee doesn't overwrite the inherited Name method, it can use self.Name() to call the Name method that it inherited at the top.

Sign up to request clarification or add additional context in comments.

1 Comment

One more question, when we need to call a method of parent class we need to pass the child (self) as an argument. Why is that so?
1

The following two methods are equivalent (assuming the "Name" method is never overridden):

class Employee(Person):
    def __init__(self, first, last, staffnum):
        Person.__init__(self, first, last)
        self.staffnumber = staffnum

    def getEmployee(self):
        return Person.Name(self) + self.staffnumber


class Employee(Person):
    def __init__(self, first, last, staffnum):
        Person.__init__(self, first, last)
        self.staffnumber = staffnum

    def getEmployee(self):
        return self.Name() + self.staffnumber

In the second example, when self.Name() is called, the instance of the class is "bound" to the function, so the first argument doesn't need to be passed.

Because init is being overridden in the Employee subclass, you can't call self.init(first, last). You'll then call Employee.init(self, *args) rather than Person.init(self, *args). This will either create an infinite recursion loop, or you'll get an argument error.

As a general rule, when you're overriding a method, you have to use the following notation in the subclass. ParentClass.methodname(self, *args, **kwargs). The reason you can call self.Name() is because name has not been overridden.

I'm repeating myself here. Does this crystalize it, or have I confused you further?

2 Comments

I'm not sure this answers the question, as it doesn't explain the difference in invocation between __init__ and Name.
It is "bound" to function means that since it has inherited the method Name() so it can also be called by self.Name()? If thats true then I am getting it. Secondly why do we need to pass self as an argument , that is pass child to parent class?
0

The simple way to say it is that self.method() means "call the most specific implementation of method available" (i.e., the one furthest down the current object's inheritance tree). In this case you don't wall to call self.__init__, because that would call Employee.__init__ again. You need to write Person.__init__ (or use super()) to explicitly call an inherited method.

Because Employee does not define its own Name method, Person.Name is the most specific one available, so that is what is called by self.Name(). If Employee defined its own Name, then that would be called by self.Name() instead.

3 Comments

Thank you so so much! I get it now! :) :)
One more question, when we need to call a method of parent class we need to pass the child (self) as an argument. Why is that so?
@ShahrozPunjwani: Whenever you call a method on a class (as in Person.__init__), you need to pass the instance as the first argument. When you call the method on the instance (as in self.Name), you don't (it is automatically passed for you).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.