Rafe Rafe - 1 month ago 7
Python Question

Python "private" name mangling and instance vs class attributes

I was writing a decorator that needs to access private variables and found this discrepancy. Can anyone explain this?

(Python 2.5)

Naming mangling works as expected for attributes defined in the class:

>>> class Tester(object):
... __foo = "hi"

>>> t = Tester()
>>> t._Tester__foo
'hi'


Instance attributes do not work (and this is the way we are supposed to do it right?)

>>> class Tester(object):
... def __init__(self):
... self.__foo = "hi"

>>> t = Tester()
>>> t._Tester__foo
AttributeError: 'Tester' object has no attribute '_Tester__foo'


P.S. Is "class attribute" the right word for these? They aren't static, but if you make one of those a list, or some other mutable type, it is shared...

Update

In fact, second example works fine, too. It was a hardware issue (restart helped).

Answer

That is actually not correct.

Name mangling takes place at class creation time; any functions that refer to mangled names are adjusted as well.

I cannot reproduce your example, at least not in Python versions 2.4, 2.5, 2.6, 3.1 and 3.2 on the Mac:

>>> class Tester(object):
...     def __init__(self):
...         self.__foo = "hi"
... 
>>> Tester()._Tester__foo
'hi'
>>> Tester().__foo
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Tester' object has no attribute '__foo'

If you disassemble the function bytecode you can see the name has been mangled as well:

>>> import dis
>>> dis.dis(Tester.__init__)
  3           0 LOAD_CONST               1 ('hi')
              3 LOAD_FAST                0 (self)
              6 STORE_ATTR               1 (_Tester__foo)
              9 LOAD_CONST               0 (None)
             12 RETURN_VALUE        

I've checked the compiler source and all names are run through the mangler, a code path that has remained the same since 2002 at least.

And yes, class attributes and instance attributes are the correct terms. Class attributes are always shared, but assignment to an attribute on an instance assigns to the instance. Mutating a list or other mutable objects is not the same as attribute assignment.