Search code examples
pythonvariablesaccessorprivate-members

How to access `conventional` private variables in python?


I have a python module, m1.

# m1.py
class C1(object):
    def __init__(self):
        self.__pri = 10
        self._pro = 5
        self.pub = 1

Then in bpython,

>>> import m1
>>> c = m1.C1()
>>> c.__pri
Traceback (most recent call last):
  File "<input>", line 1, in <module>
AttributeError: 'C1' object has no attribute '__pri'
>>> c._pro
5
>>> c.pub
1
>>> dir(c)
['_C1__pri', '__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', 
'__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_pro', 'pub']
>>> c._C1__pri
10

I thought there is no notion of private variables in python. How do we explain this behavior now?

edit: I was expecting to access c.__pri straight but it turns out that name mangling prevents me to do that as answered below. Thanks all!


Solution

  • the double underscore mangles the class name with the attribute, prefixed by a single underscore

        c._C1__pri
    

    allows access to the attribute. Sort of a pseudo-privacy, but it has other uses. I'm not sure what you expected to happen with c.__private. I think you meant to do c.__pri though the result would have been the same.

    the __pri attribute is not private because it can be accessed outside of the class, it's just a few characters extra to do so.

    as jadkik94 mentioned below, this isn't to make it impossible to access, but to signal to another programmer that they shouldn't be using the attribute.

    FYI another time this may come in handy is when using inheritance

    class Parent: 
        def __method(self): 
            print 'Parent method'
    
    class Child(Parent): 
        def __method(self): 
            print 'Child method'
    
    >>> c = Child()
    >>> c._Child__method()
    Child method
    >>> c._Parent__method()
    Parent method
    

    the double underscore prevents accidental overriding of the name (not that this is seen very often).