Why are all double-underscore variables mangled in class methods

Viewed 196

Edit: Both current answers talk about the fact that there is mangling inside classes. My question is about values inside class methods - note that the parsing in the method scope is different from the class scope, or __CLASS would be printable.


This seems to be the case in python 2.7 and 3.6.

For example, this code

__GLOBAL = 'global'
_Bar__MANGLED_GLOBAL = 'mangled global'

class Bar(object):
    __CLASS = 'class'

    def baz(self):
        __LOCAL = 'local'
        try:
            print __LOCAL
        except Exception as e:
            print e
        try:
            print __CLASS
        except Exception as e:
            print e
        try:
            print __GLOBAL
        except Exception as e:
            print e
        try:
            print __MANGLED_GLOBAL
        except Exception as e:
            print e

Bar().baz()

Will give

local
global name '_Bar__CLASS' is not defined
global name '_Bar__GLOBAL' is not defined
mangled global

I understand the logic when there is an other.__x, or needing a class-level __foo to equate to self.__foo, but this seems like an oversight, where anything inside the class scope is automatically rewritten.

2 Answers

This was not an oversight. In fact, private globals used to be specifically advertised in the tutorial:

There is now limited support for class-private identifiers. Any identifier of the form __spam (at least two leading underscores, at most one trailing underscore) is now textually replaced with _classname__spam, where classname is the current class name with leading underscore(s) stripped. This mangling is done without regard of the syntactic position of the identifier, so it can be used to define class-private instance and class variables, methods, as well as globals, and even to store instance variables private to this class on instances of other classes.

Without specific references, like a mailing list conversation or something, we can only speculate as to why it was designed this way. (I checked the commit history, but the original commit includes no justification for design choices.) We can speculate that it was to enable things like private globals, but we can also speculate that it was just easiest to implement it this way and that the implementers wouldn't have been swayed by the prospect of private globals if other options were easier. It would certainly have been a lot harder to implement name mangling in a way that only affected the class's instance and class attributes.

Update: at first, I didn't really answer the question, but according to the clues, I found the real answer at the end, so please be patient and read until the end. In short, mangling is for all the names that appear in the class.

Python class can not have real private attribute, prefix __ is for private purpose.

I have seen the below suggestion:

But try to avoid the __private form. I never use it. Trust me. If you use it, you WILL regret it later.

and:

Forms __private just trigger a private name mangling whose purpose is to prevent accidental namespace collisions in subclasses: MyClass.__private just becomes MyClass._MyClass__private.

Code Like a Pythonista: Idiomatic Python-naming

I looked private name mangling and according to it, mangling is for all names in class:

Private name mangling: When an identifier that textually occurs in a class definition begins with two or more underscore characters and does not end in two or more underscores, it is considered a private name of that class.

So, It seems that mangling is for all the names that appear in class.That is why all double-underscore variables are mangled in class methods.

Related