class User(object):
def __private_function(self):
print("private")
user = User()
print(dir(user))
Output: ['_User__private_function', '__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']
为什么 __ private_function 变为 _User__private_function
是由python内部完成的吗?
是哪种方法?
答案 0 :(得分:2)
https://github.com/python/cpython/blob/master/Python/compile.c
220 PyObject *
221 _Py_Mangle(PyObject *privateobj, PyObject *ident)
222 {
223 /* Name mangling: __private becomes _classname__private.
224 This is independent from how the name is used. */
225 PyObject *result;
226 size_t nlen, plen, ipriv;
227 Py_UCS4 maxchar;
228 if (privateobj == NULL || !PyUnicode_Check(privateobj) ||
229 PyUnicode_READ_CHAR(ident, 0) != '_' ||
230 PyUnicode_READ_CHAR(ident, 1) != '_') {
231 Py_INCREF(ident);
232 return ident;
233 }
234 nlen = PyUnicode_GET_LENGTH(ident);
235 plen = PyUnicode_GET_LENGTH(privateobj);
236 /* Don't mangle __id__ or names with dots.
237
238 The only time a name with a dot can occur is when
239 we are compiling an import statement that has a
240 package name.
241
242 TODO(jhylton): Decide whether we want to support
243 mangling of the module name, e.g. __M.X.
244 */
245 if ((PyUnicode_READ_CHAR(ident, nlen-1) == '_' &&
246 PyUnicode_READ_CHAR(ident, nlen-2) == '_') ||
247 PyUnicode_FindChar(ident, '.', 0, nlen, 1) != -1) {
248 Py_INCREF(ident);
249 return ident; /* Don't mangle __whatever__ */
250 }
251 /* Strip leading underscores from class name */
252 ipriv = 0;
253 while (PyUnicode_READ_CHAR(privateobj, ipriv) == '_')
254 ipriv++;
255 if (ipriv == plen) {
256 Py_INCREF(ident);
257 return ident; /* Don't mangle if class is just underscores */
258 }
259 plen -= ipriv;
260
261 if (plen + nlen >= PY_SSIZE_T_MAX - 1) {
262 PyErr_SetString(PyExc_OverflowError,
263 "private identifier too large to be mangled");
264 return NULL;
265 }
266
267 maxchar = PyUnicode_MAX_CHAR_VALUE(ident);
268 if (PyUnicode_MAX_CHAR_VALUE(privateobj) > maxchar)
269 maxchar = PyUnicode_MAX_CHAR_VALUE(privateobj);
270
271 result = PyUnicode_New(1 + nlen + plen, maxchar);
272 if (!result)
273 return 0;
274 /* ident = "_" + priv[ipriv:] + ident # i.e. 1+plen+nlen bytes */
275 PyUnicode_WRITE(PyUnicode_KIND(result), PyUnicode_DATA(result), 0, '_');
276 if (PyUnicode_CopyCharacters(result, 1, privateobj, ipriv, plen) < 0) {
277 Py_DECREF(result);
278 return NULL;
279 }
280 if (PyUnicode_CopyCharacters(result, plen+1, ident, 0, nlen) < 0) {
281 Py_DECREF(result);
282 return NULL;
283 }
284 assert(_PyUnicode_CheckConsistency(result, 1));
285 return result;
286 }