Can you explain me the output

Question:

I was in class section of python programming and I am confused here.

I have learned that super is used to call the method of parent class but here Employee is not a parent of Programmer yet it’s called (showing the result of getLanguage method).

What I am missing?

This is the code,

class Employee:
    company= "Google"
    language = "java"
    def showDetails(self):
        print("This is an employee");

    def getLanguage(self):
        print(f"1. The language is {self.language}");


class Programmer:
    language= "Python"
    company = "Youtubeeee"
    def getLanguage(self):
        super().getLanguage();
        print(f"2. The language is {self.language}")

    def showDetails(self):
        print("This is an programmer")



class Programmer2(Programmer , Employee):
    language= "C++"
    def getLanguage(self):
        super().getLanguage();
        print(f"3. The language is {self.language}")



p2 = Programmer2();
p2.getLanguage();

This is the output,

1. The language is C++
2. The language is C++
3. The language is C++
Asked By: Ankit

||

Answers:

You’ve bumped into one of the reasons why super exists. From the docs, super delegates method calls to a parent or sibling class of type. Python bases class inheritance on a dynamic Method Resolution Order (MRO). When you created a class with multiple inheritance, those two parent classes became siblings. The left most is first in MRO and the right one is next.

This isn’t a property of the Programmer class, Its a property of the Programmer2 class that decided to do multiple inheritance. If you use Programmer differently, as in,

p3 = Programmer()
p3.getLanguage()

You get the error AttributeError: 'super' object has no attribute 'getLanguage' because its MRO only goes to the base object which doesn’t have the method.

You can view the MRO of the class with its __mro__ attribute.

Programmer.__mro__:
    (<class '__main__.Programmer'>, <class 'object'>)

Programmer2.__mro__:
    (<class '__main__.Programmer2'>, <class '__main__.Programmer'>, 
    <class '__main__.Employee'>, <class 'object'>)
Answered By: tdelaney

Here is some more explanation about the mechanics how the code in the question works. In its general form, super() can be called with two arguments super(C, obj) where C is a class and obj is an object. The object obj determines which classes should be searched for a given attribute and the Method Resolution Order (MRO) in which these classes should be searched. The class argument is used to restrict this search to only these classes that appear in MRO after C.

By PEP 3135 when super() is used without arguments inside a class definition, the class argument is automatically taken to be the class being defined, and the object argument is the object upon which super acts.

In the code in the question, when you call p2.getLanguage() then inside the definition of Programmer2, the code super().getLanguage() is tacitly replaced by super(Programmer2, p2).getLanguage(). MRO of p2 is Programmer2 -> Programmer -> Employee -> object, and the search for getLanguage starts after Programmer2 i.e. with Programmer class, and it succeeds in this class.

Then, in the process of executing getLanguage method of Programmer, we again encounter super().getLanguage(). This is now replaced by super(Programmer, p2).getLanguage() since we are still working with the same object, but the call to super is inside Programmer class. MRO of p2 is still Programmer2 -> Programmer -> Employee -> object, but now the search for getLanguage starts after Programmer i.e. with Employee class, and it succeeds in this class.

In this way, even though Programmer does not inherit from Employee, the code super().getLanguage() inside Programmer succeeds, since it is applied to an object that has Employee in its MRO.

Answered By: bb1
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.