13
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?