I've just run into a situation where pseudo-private class member names aren't getting mangled when using setattr or exec.

In [1]: class T:
   ...:     def __init__(self, **kwargs):
   ...:         self.__x = 1
   ...:         for k, v in kwargs.items():
   ...:             setattr(self, "__%s" % k, v)
   ...:         
In [2]: T(y=2).__dict__
Out[2]: {'_T__x': 1, '__y': 2}

I've tried exec("self.__%s = %s" % (k, v)) as well with the same result:

In [1]: class T:
   ...:     def __init__(self, **kwargs):
   ...:         self.__x = 1
   ...:         for k, v in kwargs.items():
   ...:             exec("self.__%s = %s" % (k, v))
   ...:         
In [2]: T(z=3).__dict__
Out[2]: {'_T__x': 1, '__z': 3}

Doing self.__dict__["_%s__%s" % (self.__class__.__name__, k)] = v would work, but __dict__ is a readonly attribute.

Is there another way that I can dynamically create these psuedo-private class members (without hard-coding in the name mangling)?


A better way to phrase my question:

What does python do “under the hood” when it encounters a double underscore (self.__x) attribute being set? Is there a magic function that is used to do the mangling?

Edit
Report