想改善这个问题吗?更新问题,使其仅通过editing this post专注于一个问题。
2年前关闭。
当我遇到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
是在Python代码中执行len(foo)
时调用的那个。函数的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
获取给定对象的大小。错误发生时,将为当前线程设置一个引发异常,并返回一个数字return NULL;
表示调用方发生了异常,并且必须采取相应的措施-如果它是Python字节码中的函数调用指令,它将导致引发异常;如果是C代码,则它将以类似于此函数的方式工作-如果发生异常,则返回NULL或无效值;或者它可以清除异常或将其替换为另一个。
否则,如果大于或等于0,则通过返回现有的Py_ssize_t res
对象或构造一个新的对象,将C整数类型的int
转换为Python int
对象。由于历史原因,Python int
对象在CPython 3中称为PyLong
。 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/