Early last year, I wrote about class-based access privileges in object-oriented programming (OOP). I was surprised by something Cay S. Horstmann wrote in Core Java: You know that a method can access the private data of the object on which it is invoked. What people often find surprising is that a method can access the private data of all objects of its class. The other day, I was testing whether this worked in Python when I discovered something unusual about its implementation.

Private class fields in Python

In Python, private class fields are prefixed with two underscores. As expected, you cannot directly access the private fields from outside the class. You have to use a getter method. However, the private fields are not truly private. The interpreter merely hides them through a process known as private name mangling:

When an identifier that textually occurs in a class definition begins with two or more underscore characters and does not end in two or more underscores, it is considered a private name of that class. Private names are transformed to a longer form before code is generated for them. The transformation inserts the class name, with leading underscores removed and a single underscore inserted, in front of the name. For example, the identifier __spam occurring in a class named Ham will be transformed to _Ham__spam.

In the following example, we define a Person class with a private field __name. We cannot access the private field from outside the class; we have to use a getter method. However, we can still access the private field via its mangled name!

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

# A method can access the private data of all objects of its class.
def get_name(self):
return self.__name


person = Person("kieran")

# We cannot directly access the private field from outside the class.
try:
print(person.__name)
except AttributeError as error:
print(error)

# To access the private field, we have to use a getter method.
print(person.get_name())

# However, we can still access the private field via its mangled name!
print(person._Person__name)

A curious decision

Before private class fields were added to JavaScript, we prefixed them with a single underscore by convention only. The underscores were merely a warning to indicate that the fields were not supposed to be modified outside the class. However, now that we have private class fields enforced by the language, they are truly private.

I am a fan of the Python language, but I find it curious that the language designers chose to mangle the field names instead of making them truly private. Was it considered to be more “Pythonic” even though it breaks encapsulation? If you are a Pythonista who can enlighten me, I would be genuinely interested to hear from you!