python - C实现python的len函数解释

标签 python c cpython python-internals

当我遇到这个 len 函数的 C 实现时,我正在阅读有关 python 内置函数的实现

static PyObject *
builtin_len(PyObject *module, PyObject *obj)
/*[clinic end generated code: output=fa7a270d314dfb6c input=bc55598da9e9c9b5]*/
{
Py_ssize_t res;

res = PyObject_Size(obj);
if (res < 0) {
    assert(PyErr_Occurred());
    return NULL;
}
return PyLong_FromSsize_t(res);

我无法理解这段代码中发生了什么。我不知道C是如何工作的。有人能解释一下这段代码是做什么的吗?

我从 https://github.com/python/cpython/blob/master/Python/bltinmodule.c 获取了代码

编辑:我只是好奇 len 函数为何如此之快,并偶然发现了这段代码。我只是想知道为什么使用函数 PyObject_Size 来检查对象的大小是否为零,然后使用 PyLong_FromSsize_t 返回实际大小。

最佳答案

这个函数没有什么特别的。通常用 C 编写的函数,尤其是那些不调用 Python 代码的函数,比用 Python 编写的函数要快得多。

我在这里特别采取的立场是,读者知道 C 是如何工作的,否则解释就像一本书。

builtin_len是当 len(foo) 时被调用的那个在Python代码中执行。 PyObject *obj函数的参数引用作为参数给出的对象 ( foo ),和 PyObject *self将包含对 builtin_len 的包含模块的引用.

Python 中每个容器的长度必须介于 0 和 Py_ssize_t 允许的最大值之间。 。 PyObject_Size(obj);是一个函数/宏,通过其 obj->ob_type->tp_as_sequence->sq_length 获取给定对象的大小或obj->ob_type->tp_as_mapping->mp_length 。出错时,将设置为当前线程引发的异常,并返回数字 < 0 (-1)。

return NULL;表示调用者发生了异常,并且必须采取相应的行动 - 如果它是Python字节码中的函数调用指令,则会导致引发异常;如果它是 C 代码,那么它将以类似于此函数的方式运行 - 如果发生异常,则返回 NULL 或无效值;或者它可以清除异常或将其替换为另一个异常。

否则如果大于或等于0,则 Py_ssize_t res它是 C 整数类型,转换为 Python int 对象,通过返回现有的 int对象或构造一个新对象。 Python int对象被称为 PyLong由于历史原因在 CPython 3 中。 PyLong_FromSsize_t()是众多函数之一 - 该函数能够转换 Py_ssize_t 类型的任何值到 Python int具有相同的值。与所有其他对象一样,对此对象的引用保留为指向(半不透明)PyObject 的指针。结构,并返回该值。

assert(PyErr_Occurred());是仅在 Python 的调试版本中有效的断言。它断言,当从 PyObject_Size 得到负数时,表示抛出异常,该异常也已正确设置;如果不存在,它将彻底中止整个 CPython 进程。它在 Python 的发布版本中不起作用,因为“断言永远不会失败”。

关于python - C实现python的len函数解释,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53988132/

相关文章:

python - 如何将此 Python 2.7 代码转换为 Python 3?

python - 从二维数组中,创建另一个由原始数组中随机选择的值(行之间不共享的值)组成的二维数组,而不使用循环

python - 使用 python 文件启动 ipython notebook

python - 如何仅更改 pandas Dataframe barplot 中的 xticks 字体大小?

c - 为什么这个程序不报错?

c - 主函数中循环运行错误

java - 在 Java 中嵌入 CPython 时,为什么会挂起?

Python C 模块 - Malloc 在特定版本的 Python 中失败

python - 应用多个条件级别的 groupby

在 C 函数中更改函数参数值