0

I am very new to Python. Here is some test code:

class Test():
  def __init__(self,num,option):
    self.__num = num
    self.option = option
  def getNum(self):
    return self.__num
  def getOption(self):
     return self.option
  
   


my_num = Test(77,1)
print(my_num.getNum())    // 77
print(my_num._Test__num)  // 77
print(my_num.__num)       // Attribute error

My question is:

Why my_num.getNum() returns 77?

Why self.__num through getNum has value and my_num.__num returns error?

self in self.__num points to my_num, isn't it? Since __num is a private property, how is it accessible through self whereas self points to an object?

Unknown developer
  • 5,414
  • 13
  • 52
  • 100
  • In Python comments start with `#` – Arkadiusz Drabczyk Feb 13 '22 at 15:18
  • 1
    It's called name mangling. See [docs](https://docs.python.org/3/tutorial/classes.html#private-variables). – ken Feb 13 '22 at 15:23
  • Some more info here too: [pep8](https://www.python.org/dev/peps/pep-0008/#descriptive-naming-styles) – cglacet Feb 13 '22 at 15:24
  • "Why my_num.getNum() returns 77?" What do you think it should return instead? Why? "Since __num is a private property, how is it accessible through self whereas self points to an object?" I don't understand the objection. Properties belong to objects. `getNum` is a *method of the class*, so of course it can directly access attributes by their actual name. – Karl Knechtel Feb 13 '22 at 15:29

1 Answers1

0

In the constructor, you're passing value 77, which gets assigned to self.__num. Later when you request .getNum() it's simply passing the same self.__num back to you, so you get 77 back. The best way to think of self is like this in other languages, it's referencing the instantiated object itself.

You get an error on calling .__num directly because of name mangling, instead it's been renamed to ._Test__num.

What you're encountering is something called name mangling.

Specifically:

A double underscore prefix causes the Python interpreter to rewrite the attribute name in order to avoid naming conflicts in subclasses.

That is why you are able to reference ._Test__num and not .__num. There's a StackOverflow question with more in-depth answers here: Python name mangling

Mendhak
  • 8,194
  • 5
  • 47
  • 64
  • Name mangling was not my issue/question. What I cannot understand is how `self.__num` inside `getNum` method returns 77 since `self` points to `my_num` object and `my_num` does not have ` __num` property... – Unknown developer Feb 13 '22 at 16:09
  • Answer edited to include the self bit. The latter part of the question is related to name mangling. – Mendhak Feb 13 '22 at 18:09