How to access "__" (double underscore) variables in methods added to a class
Name mangling happens when the methods in a class are compiled. Attribute names like __foo
are turned in to _ClassName__foo
, where ClassName
is the name of the class the method is defined in. Note that you can use name mangling for attributes of other objects!
In your code, the name mangling in newfunction2
doesn't work because when the function is compiled, it's not part of the class. Thus the lookups of __cat
don't get turned into __Test_cat
the way they did in Test.__init__
. You could explicitly look up the mangled version of the attribute name if you want, but it sounds like you want newfunction2
to be generic, and able to be added to multiple classes. Unfortunately, that doesn't work with name mangling.
Indeed, preventing code not defined in your class from accessing your attributes is the whole reason to use name mangling. Usually it's only worth bothering with if you're writing a proxy or mixin type and you don't want your internal-use attributes to collide with the attributes of the class you're proxying or mixing in with (which you won't know in advance).
You can use <Test instance>._Test__cat
to access the __cat
attribute from the Test
class. (where <Test instance>
is replaced by self
or any other instance of the Test
class)
learn more in the Python doc
To answer both of your questions:
- You will need to change
self.__cat
when you need to call it fromnewfunction2
toself._Test__cat
thanks to the name mangling rule.
- Python documentation:
This mangling is done without regard to the syntactic position of the identifier, as long as it occurs within the definition of a class.
Let me brake it down for you, it's saying that it doesn't matter where your interpreter is reading when it encounters a name mangled name. The name will only be mangled if it occurs in the definition of a class, which in your case, it's not. Since it's not directly "under" a class definition. So when it reads self.__cat
, it's keeping it at self.__cat
, not going to textually replace it with self._Test__cat
since it isn't defined inside theTest
class.