There is nothing special with this function. Usually the functions written in C, especially those that do not call Python code, are much faster than ones written in Python.
I am specifically taking the stance here that a reader knows how C works, otherwise the explanation would rather be a book.
The builtin_len
is the one that is called when len(foo)
is executed in Python code. The PyObject *obj
argument to the function references the object given as the argument (foo
), and PyObject *self
will contain a reference to the containing module of builtin_len
.
Each container in Python must have a length between 0 and the maximum value allowed by Py_ssize_t
. PyObject_Size(obj);
is a function/macro that gets the size of the given object through its obj->ob_type->tp_as_sequence->sq_length
or obj->ob_type->tp_as_mapping->mp_length
. Upon error an exception is set as raised for the current thread and a number < 0 (-1) is returned.
The return NULL;
signifies the caller that an exception has occurred and it must act accordingly – if it is a function call instruction in Python bytecode, it will cause an exception to be raised; if it is C code, then it will behave in a manner similar to this function – returning NULL or invalid value if an exception occurred; or it can clear the exception or replace it with another one.
Otherwise if greater than or equal to 0, the Py_ssize_t res
which is of a C integer type, is converted to a Python int
object, by either returning an existing int
object or constructing a new one. The Python int
object is called PyLong
in CPython 3 for historical reasons. PyLong_FromSsize_t()
is one of many functions – this one is able to convert any value of type Py_ssize_t
to a Python int
with the same value. The reference to this object, like all other objects, are kept as pointers to the (semi-opaque) PyObject
structure, and this is returned.
The assert(PyErr_Occurred());
is an assertion that is in effect in debug builds of Python only. It asserts that upon getting a negative number from PyObject_Size
, signifying an exception being thrown, the exception has also been properly set; if not present, it will abort the entire CPython process outright. It isn’t in effect in release builds of Python because “asserts never fail”.
2
solved explanation of C implementation python’s len function [closed]