Python private instance variable behavior

Viewed 98

The following piece of code:

class A:
    def __init__(self):
        self.__var = 123
    def getV(self):
        return self.__var
a = A()
a.__var = 10
print a.getVar(), a.__var

prints 123 10. Why does this behavior occur? I would expect a.getVar() to print out 10. Does the class internally interpret self.__var as self._A__var?

1 Answers

The double underscore attributes in Python has a special effect, it does "name mangling" that is it converts the attribute __var to _A__var i.e. _<classname>__<attributename> at runtime.

In your example when you assign 10 to the attribute __var of a object, it is essentially creating a new attribute __var and not modifying the self.__var. This is because the self.__var is now _A__var due to name mangling.

This can be seen if you print the __dict__ of the a object:

class A:
    def __init__(self):
        self.__var = 123
    def getV(self):
        return self.__var
a = A()
print (a.__dict__)

>> {'_A__var': 123}

If you don't assign any value to __var and try to print it directly, it will result in an AttributeError:

class A:
    def __init__(self):
        self.__var = 123
    def getV(self):
        return self.__var
a = A()
print (a.__var)

>> AttributeError: 'A' object has no attribute '__var'

Now if you try to assign to the new mangled attribute name, you would get the right result (but this process is meant to prevent accidental usage of such variables):

class A:
    def __init__(self):
        self.__var = 123
    def getV(self):
        return self.__var
a = A()
a._A__var = 10
print (a.getV())

>> 10
Related