1

Here's the code:

class Person:
    def __getInfo(self):
        return "Person"

    def printPerson(self):
        print(self.__getInfo())

class Student(Person):
    def __getInfo(self):
        return "Student"

Person().printPerson() # output: person
Student().printPerson() # output: person

My question is why the "private" method of the second class (Student) is not invoked when the "public" method (printPerson()) is invoked? And why do they all invoke __getInfo() in the baseclass?

Mughees
  • 832
  • 7
  • 16
Baozhe
  • 29
  • 5
  • 4
    The point of `__*` attributes is specifically to avoid an attribute in your subclass interfering with the attribute in your base class. If you want a method you can override, don't start its name with `__`. – khelwood Aug 06 '20 at 11:50

1 Answers1

3

This happens because of name mangling in Python. Any identifier of the form __spam (at least two leading underscores, at most one trailing underscore) is textually replaced with _classname__spam, where classname is the current class name with leading underscore(s) stripped. For example -

class Demo:
    __any_name = "__any_name"
    __any_other_name_ = "__any_other_name_"
>>> [n for n in dir(Demo) if 'any' in n]
['_Demo__any_name', '_Demo__any_other_name_']

To call your derived class (Student) function, you could do something like this -

class Person:
    def printPerson(self):
        print(self._Student__getInfo())

But in this case your statement Person().printPerson() will throw an error.

You can read more about it here - https://docs.python.org/3/tutorial/classes.html#private-variables

Tabaene Haque
  • 576
  • 2
  • 10