Python为私有方法添加类名的位置

时间:2017-12-16 06:34:09

标签: python python-3.x python-2.7

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内部完成的吗?

是哪种方法?

1 个答案:

答案 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 }