Ehsan Sh
Ehsan Sh

Reputation: 237

python id() function implementation

How are python built-in functions are implemented? Some of them like issubclass are wrappers around object methods.

About id() Documentation says that:

For CPython, id(x) is the memory address where x is stored.

When talking about id(), other places in documentation do not say anything more!

So how has id() been implemented? I think it doesn't have to do with any methods of the object in Cpython API. Just to have them, I used 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__']

Upvotes: 1

Views: 1215

Answers (1)

tdelaney
tdelaney

Reputation: 77337

There are multiple implementations of python. In cpython, all objects have a standard header and the id is the memory address of that header. References to objects are C pointers to their object header (that same memory address that is the id). You can't use a dunder method to find an object because you need the object pointer to find the dunder methods.

Python is compiled into byte code and that byte code is executed by C. When you call a function like id, that function can be more byte code, but it can also be a C function. Search for "builtin_id" in bltinmodule.c and you'll see the C implementation of id(some_object).

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;
}

The id function is called with PyObject *v, a pointer to the object whose id should be taken. PyObject is the standard object header used by all python objects. It includes information needed to figure out what type the object really is. The id function turns the object pointer into a python integer with PyLong_FromVoidPtr (the name "long" for a python int is somewhat historical). That's the id you see at the python level.

You can get the 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

Upvotes: 3

Related Questions