Chapter 3: Encapsulation

Non-public attributes

face Josiah Wang

As an example, let’s say we have the class definition for VainPerson with the attribute name.

class VainPerson:
    def __init__(self, name):
        self.name = name

lovely_person = VainPerson("Beauty")
print(lovely_person.name) # Beauty
lovely_person.name = "Average"
print(lovely_person.name) # Average

VainPerson definitely does not like people assigning it random names. It also does not like people knowing its real name! No, that should be kept secret! 🤐🤐🤐

You can make an attribute non-public by adding a double underscore before its name.

class VainPerson:
    def __init__(self, name):
        self.__name = name

lovely_person = VainPerson("Beauty")
print(lovely_person.__name) # AttributeError: 'VainPerson' object has no attribute '__name'

If you try this out, you will see that __name cannot be accessed directly anywhere else other than inside VainPerson class. Python has performed what is known as name mangling to hide this variable from public view. There is a way to access it if you are really desperate (it’s via lovely_person._VainPerson__name), but you really should not be doing this! 👎

If you have previously come across OOP, you might have also noticed that I used the word non-public rather than the more conventional term “private”. This is because no variables are really private in Python (even __name can be accessed as mentioned)! Python’s philosophy is to be ‘open’.

If you try to set lovely_person.__name = "A new name", it does work. BUT it actually refers to a new attribute __name and not the one you defined in the class (that one has been automatically renamed to _VainPerson__name).