python - C实现python的len函数解释
问题描述
当我遇到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 是如何工作的,否则解释宁愿是一本书。
是在 Python 代码中执行builtin_len
时调用的那个。len(foo)
函数的PyObject *obj
参数引用作为参数 ( foo
) 给出的对象,PyObject *self
并将包含对 的包含模块的引用builtin_len
。
Python 中的每个容器的长度必须介于 0 和Py_ssize_t
. 是一个函数/宏,它通过它的orPyObject_Size(obj);
获取给定对象的大小。发生错误时,会为当前线程设置一个异常,并返回一个 < 0 (-1) 的数字。obj->ob_type->tp_as_sequence->sq_length
obj->ob_type->tp_as_mapping->mp_length
表示调用者发生了异常,它必须采取相应的return NULL;
行动——如果它是 Python 字节码中的函数调用指令,则会引发异常;如果它是 C 代码,那么它将以类似于此函数的方式运行 - 如果发生异常,则返回 NULL 或无效值;或者它可以清除异常或用另一个替换它。
否则,如果大于或等于 0,则属于 C 整数类型,通过返回现有对象或构造新对象,Py_ssize_t res
将其转换为 Python对象。由于历史原因,Python对象在 CPython 3 中被调用。是许多函数之一 - 这个函数能够将任何类型的值转换为具有相同值的 Python 。与所有其他对象一样,对该对象的引用作为指向(半透明)结构的指针保存,并返回 this。int
int
int
PyLong
PyLong_FromSsize_t()
Py_ssize_t
int
PyObject
这assert(PyErr_Occurred());
是一个仅在 Python 的调试版本中有效的断言。它断言,在从 中获得负数时PyObject_Size
,表示抛出异常,该异常也已正确设置;如果不存在,它将彻底中止整个 CPython 进程。它在 Python 的发布版本中无效,因为“断言永远不会失败”。
推荐阅读
- javascript - 如何在同一 HTML 中发布操作后显示部分 HTML?
- sql - 如何按日期分组并获得所有进出时间?
- xamarin.forms - 点击背景上的 Xamarin 表单选择器
- python - Python循环中的变量不是块作用域吗?
- node.js - MongoDB `updateOne()` 返回的文档实际记录在哪里?
- spring - 微服务间通信部分失败如何处理?
- python - 在 Python 中使用 pandas 在现有 excel 中添加多个工作表
- reporting-services - 报告标题在 SSRS 报告的新页面上不可见
- ios - 如何将过滤器应用于照片库中的选定图像,而不仅仅是硬编码的图像
- unity3d - 每次发生碰撞时如何继续协程功能?