0

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!

4
  • What do you want from us?) Yes, it does work like this. Commented Dec 26, 2012 at 15:19
  • what did you expected here? Commented Dec 26, 2012 at 15:21
  • 2
    This is extensively documented (docs.python.org/2/tutorial/…), please do some research before asking a question like this. Commented Dec 26, 2012 at 15:22
  • @l4mpi Well, I did my homework and researched but was unlucky to miss that point. @alexvassel The question is clearly how you do explain this not to mention it works like that. And people down there kindly referred to name mangling. Commented Dec 26, 2012 at 15:33

3 Answers 3

5

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

Sign up to request clarification or add additional context in comments.

3 Comments

You should mention that the whole point of this is not meant to be private as in "you cannot use this", but private as you "shouldn't need to use this"
@jadkik94 I like your comment. Very much telling. Thx
@xhainingx Thanks very much for detailing the answer.
1

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.

Comments

1

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.