python id()函数实现

python id() function implementation

python内置函数是如何实现的?其中一些像 issubclass 是对象方法的包装器。

关于 id() Documentation 说:

对于CPython,id(x)是存储x的内存地址。

文档中说到id()时,other places不要再说了!

那么 id() 是如何实现的呢?我认为它与CpythonAPI中对象的任何方法无关。为了拥有它们,我使用了 dir(x):

foo = [1,2,3]
dir(foo)

>> ['__add__',
 '__class__',
 '__contains__',
 '__delattr__',
 '__delitem__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__getitem__',
 '__gt__',
 '__hash__',
 '__iadd__',
 '__imul__',
 '__init__',
 '__init_subclass__',
 '__iter__',
 '__le__',
 '__len__',
 '__lt__',
 '__mul__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__reversed__',
 '__rmul__',
 '__setattr__',
 '__setitem__',
 '__sizeof__',
 '__str__',
 '__subclasshook__']

python 有多种实现。在cpython中,所有的对象都有一个标准的header,id就是那个header的内存地址。对对象的引用是指向它们的对象头的 C 指针(与 id 相同的内存地址)。您不能使用 dunder 方法来查找对象,因为您需要对象指针来查找 dunder 方法。

Python被编译成字节码,那个字节码被C执行。当你调用一个像id这样的函数时,那个函数可以是更多的字节码,但也可以是一个C函数。在 bltinmodule.c 中搜索“builtin_id”,您将看到 id(some_object).

的 C 实现
static PyObject *
builtin_id(PyModuleDef *self, PyObject *v)
/*[clinic end generated code: output=0aa640785f697f65 input=5a534136419631f4]*/
{
    PyObject *id = PyLong_FromVoidPtr(v);

    if (id && PySys_Audit("builtins.id", "O", id) < 0) {
        Py_DECREF(id);
        return NULL;
    }

    return id;
}

id 函数使用 PyObject *v 调用,一个指向应获取其 id 的对象的指针。 PyObject 是所有 python 对象使用的标准对象头。它包括确定对象真正是什么类型所需的信息。 id 函数将对象指针转换为具有 PyLong_FromVoidPtr 的 python 整数(python int 的名称“long”有点历史)。这是您在 python 级别看到的 ID。

你可以获得cpython source on github and you can read up on C in the python docs at Extending and Embedding the Python Interpreter and Python/C API Reference Manual