Name mangling happens anywhere in a class body according to the docs:
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 ... This transformation is independent of the syntactical context in which the identifier is used.
The tutorial example shows that the mangling happens to attributes within the class too.
But the real problem is that your code is confusing namespaces. The constructor you showed originally
def __init__(self, x):
__x = x
creates a local variable _test__x
, which gets discarded as soon as it completes.
To properly assign an instance attribute:
def __init__(self, x):
self.__x = x
This will create an attribute whose name is actually _test__x
.
If you actually want to assign the global:
def __init__(self, x):
global __x
__x = x
Or
def __init__(self, x):
global _test__x
__x = x
The getter needs to access the instance attribute just as the constructor needs to set it. The current version is accessing the global because the name _tesy__x
does not exist in the local namespace:
def rex(self):
return __x
To return an attribute, add the namespace:
def rex(self):
return self.__x
All that being said, if you had a module-level attribute with a leading double underscore (which you just shouldn't do), you would have a very hard time accessing it in the class. You would have to go through globals
, something like this:
globals()['__x']
Shameless plug of my question about that from a long time ago: How to access private variable of Python module from class.
Another fun fact: name mangling won't happen at all if your class name is all underscores. You can escape all your problems by naming classes _
, __
, ___
, ____
, etc.