0

I am taking a Python OOP course and, by playing with the code in the course, I stumbled upon something interesting.

Suppose I have this code:

class genericClass:
   def __init__(self):
      self.__secret = "secret"

generic_object = genericClass()

print(generic_object.__secret)

When I run this code I get the following error:

AttributeError: 'genericClass' object has no attribute '__secret'

But if I do the following:

class genericClass:
   def __init__(self):
      self.__secret = "secret"

generic_object = genericClass()

generic_object.__secret = "not a secret anymore" #set a different value for the '__secret attribute
print(generic_object.__secret)

Everything works and the message is printed to my terminal.

How does this happen? Does this specific instance now have 2 '__secret' attributes? If yes, how does Python differentiate between the two? If not, what is going on?

Emi Buliga
  • 43
  • 7
  • 2
    No, it has one `__secret` attribute and one "name mangled" `_genericClass__secret` attribute - you can see them both in `genericObject.__dict__`. If you wanted to access the attribute from outside the instance, you shouldn't have prefixed the name with `__`. – jonrsharpe Jul 29 '22 at 10:28
  • @jonrsharpe I am aware I should not have prefixed the name with __ if I wanted to access it outside the instance. I was talking about a very specific case, but you answered my question, nonetheless. My question now is: if Python automatically prefixes the name of attributes that start with '__', then why does it not do the same to the attribute I set on my 'genericObject' object? – Emi Buliga Jul 29 '22 at 10:34
  • 1
    Because the prefixing/mangling is only applied _inside the class body_, precisely so you can write e.g. `return "*" * len(self.__secret)` in an instance method without having to keep adding the class name manually. Really it's to avoid conflicts with other classes in the MRO, _not_ to make the attribute private - see https://stackoverflow.com/a/34903236/3001761, https://peps.python.org/pep-0008/#method-names-and-instance-variables. – jonrsharpe Jul 29 '22 at 10:35

0 Answers0