Advanced attribute access patterns

When many C++ and Java programmers first learn Python, they are surprised by Python's lack of a private keyword. The nearest concept is name mangling. Every time an attribute is prefixed by __, it is renamed by the interpreter on the fly:

class MyClass: 
    __secret_value = 1 

Accessing the __secret_value attribute by its initial name will raise an AttributeError exception:

>>> instance_of = MyClass()
>>> instance_of.__secret_value
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'MyClass' object has no attribute '__secret_value'
>>> dir(MyClass)
['_MyClass__secret_value', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']
>>> instance_of._MyClass__secret_value
1  

This feature is provided to avoid name collision under inheritance, as the attribute is renamed with the class name as a prefix. It is not a real privacy lock, since the attribute can be accessed through its composed name. This feature could be used to protect the access of some attributes, but, in practice, __ should never be used. When an attribute is not public, the convention to use is a _ prefix. This does not invoke any name mangling algorithm, but just documents the attribute as a private element of the class and is the prevailing style.

Other mechanisms are available in Python that nicely separate the public part of the class together with the private code. The descriptors and properties are interesting features of Python that allow us to cleanly provide this kind of separation.