在 Python 中的现有迭代器上使用 iter:迭代器会发生什么情况?

Using iter on an existing iterator in Python: What happens to the iterator?

iter function 包装列表或元组等对象,以便将它们用作迭代器,例如,可以使用 next。例如,

next(iter([1, 2, 3]))

returns 1.

如果我们传递给 iter 的对象已经是一个迭代器,内部会发生什么?它只是 return 原始对象,即无操作吗?或者它会产生一个新的迭代器来包装原来的迭代器吗?当然,包装并不是指复制原始迭代器。

TLDNR:iter returns obj.__iter_。它没有 return obj "as is".

iter 的 Cpython 实现非常简单:

PyObject *
PyObject_GetIter(PyObject *o)
{
    PyTypeObject *t = o->ob_type;
    getiterfunc f = NULL;
    if (PyType_HasFeature(t, Py_TPFLAGS_HAVE_ITER))
        f = t->tp_iter; // <- if it has __iter__, return that
    ....more stuff

因此,当您调用 iter(obj) 并且 obj.__iter__ 存在时,它只是 return。大多数(全部?)内置迭代器有 __iter__ = self,例如

PyTypeObject PyListIter_Type = {
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
    "listiterator",                             /* tp_name */
    ....
    PyObject_SelfIter,                          /* tp_iter */
    ....

但这对于用户空间对象来说不是必需的:

class X:
    def __iter__(self):
        return Y()

class Y:
    def __iter__(self):
        return iter('xyz')


a = iter(X())
b = iter(a)
print a is b # False

经验证据很好,但是 the docs are pretty explicit

Iterators are required to have an __iter__() method that returns the iterator object itself

如果您使用 __next__() 实现一个对象,您应该有一个 returns self__iter__() 方法。违反这条规则意味着你有一个不是迭代器但看起来像迭代器的对象,这是灾难的接收者。