7

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

3
  • 2
    Class attribute is the right word. And they are always shared. Mutability does not matter. It pretty much never matters, except when asking if you can mutate a given object. Commented Sep 21, 2012 at 20:55
  • Can I nuke this question? Or does anyone see value in keeping it? I can't reproduce my original issue. It seems to work as expected. Commented Sep 22, 2012 at 0:38
  • 1
    Rather leave it around, since @MartijnPieters went all the way on testing the issue in a lot of Python testings. Commented Sep 22, 2012 at 2:37

1 Answer 1

11

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.

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

1 Comment

You are right. I have no idea what happened there. I happen to restart my computer, so I'll just have to call it an IT issue, "Have you tried turning it off and on again?" ;)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.