Question

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!

Was it helpful?

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).

OTHER TIPS

What you are observing is name mangling, in which the name of a variable with two leading underscores and at most one trailing underscore is renamed to prevent accidental collisions with subclasses and prevent the casual hacker from modifying the private field.

However, it is pretty easy to determine what the variable's name is after mangling, so it won't foil a determined pathological user.

Name Mangling

This provides a method to declare a private class member.

This double underscore name mangling helps to prevent overwriting of a internal private variable in sub classes.

The typical way to show that a member variable should not be used is to proceed it by a single underscore, although this is just a convention.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top