Show Python name mangling with a double underscore, and how to reach the attribute anyway.
An attribute whose name starts with two underscores is mangled by the interpreter. The interpreter puts the class name in front of it, so that it cannot accidentally clash with an attribute of the same name in a subclass.
class Account:
def __init__(self, balance):
self.__balance = balance
def get_balance(self):
return self.__balance
def set_balance(self, value):
if value < 0:
raise ValueError('balance cannot be negative')
self.__balance = value
acc = Account(100)
print(acc.get_balance()) # 100
acc.set_balance(150)
print(acc.get_balance()) # 150
# The real attribute name is mangled.
print(acc._Account__balance) # 150
try:
print(acc.__balance)
except AttributeError as error:
print('AttributeError:', error)
The attribute really does exist, but under the name _Account__balance. Inside the class body, the compiler rewrites every reference to __balance, so the public methods all see the same mangled attribute and everything works in a consistent way.
The access from outside the class fails because acc.__balance is looked up exactly as it is written, and there is no attribute with that exact name. The mangled name can still be reached, as the third block shows. Mangling is a change of name and not a way of locking the data away.
Notice the check inside set_balance. Because the attribute is meant to stay private, a public method that checks the value before storing it is the normal way to keep the object in a valid state.