__next__ 和 __str__ 是否由等效的 next 和 str 函数在内部调用?

Are __next__ and __str__ invoked by the equivalent next and str functions internally?

来自 Learning python 书第 5 版:

Page 421, footnote2:

Technically speaking, the for loop calls the internal equivalent of I.__next__, instead of the next(I) used here, though there is rarely any difference between the two. Your manual iterations can generally use either call scheme.

这到底是什么意思?这是否意味着 I.__next__ 由 C 函数调用,而不是 for 循环或任何内置迭代上下文中的 str 内置函数?

Page 914:

__str__ is tried first for the print operation and the str built-in function (the internal equivalent of which print runs). It generally should return a user-friendly display.

除了书本之外,Python 是否像我从书中理解的那样在内部使用 C 函数调用 __str____next__

Python C 实现使用的 C 函数 本质上 与 Python 函数相同,因为 Python 函数类似于str()next() 通常是 C 函数的薄包装。

然后这些 C 函数负责调用正确的钩子;这可能是钩子的 C 版本(结构中指向函数的槽),或 class.

上的 Python 函数

现在,str()next() 在这里都比包装器多一点,因为这些函数定义了额外的功能,需要更多的实现工作;例如,next() 采用定义默认值的第二个参数。

所以我将以len()为例。该函数定义在 builtin_len() C function:

static PyObject *
builtin_len(PyObject *self, PyObject *v)
{
    Py_ssize_t res;

    res = PyObject_Size(v);
    if (res < 0 && PyErr_Occurred())
        return NULL;
    return PyInt_FromSsize_t(res);
}

注意调用PyObject_Size();这就是 C 代码用来获取对象长度的方法。剩下的只是错误处理和生成 Python int 对象。

PyObject_Size() 那么就是 implemented like this:

Py_ssize_t
PyObject_Size(PyObject *o)
{
    PySequenceMethods *m;

    if (o == NULL) {
        null_error();
        return -1;
    }

    m = o->ob_type->tp_as_sequence;
    if (m && m->sq_length)
        return m->sq_length(o);

    return PyMapping_Size(o);
}

它接受一个PyObject结构,从那里找到ob_type结构,它有一个可选的tp_as_sequence结构,它可以定义一个sq_length函数指针。如果存在,则调用它来产生实际长度。不同的类型可以定义该函数,并且 Python 实例的特殊 C 结构可以处理重定向回 Python 方法。

所有这些都表明 Python 的内部实现使用了大量抽象来实现对象,允许 C 定义的类型和 Python classes 被同等对待, 大多数情况下。如果您想深入挖掘,Python 文档有 full coverage of the C-API, including a dedicated tutorial.

回到原来的两个函数,next() 的内部等价物是 PyIter_Next(), and str(), as used for string conversions of arbitrary objects, is PyObject_Str()