Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

The iter function wraps objects like lists or tuples in order to use them as iterators, i.e. one is able to use next, for example. For instance,

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

returns 1.

What happens internally if the object we pass to iter is already an iterator? Does it simply return the original object, i.e. no-op? Or does it produce a new iterator wrapping the original one? And by wrapping I don't mean copying the original iterator, of course.

like image 315
SmCaterpillar Avatar asked Sep 28 '22 15:09

SmCaterpillar


2 Answers

TLDNR: iter returns obj.__iter_. It doesn't return obj "as is".

The Cpython implementation of iter is pretty straightforward:

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

So when you call iter(obj) and obj.__iter__ exists it just returns that. Most (all?) built-in iterators have __iter__ = self, e.g.

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

but that's not necessary true for userland objects:

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
like image 200
georg Avatar answered Oct 13 '22 08:10

georg


Empirical evidence is nice, but the docs are pretty explicit.

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

If you implement an object with a __next__(), you should have an __iter__() method that returns self. Breaking this rule means you have an object that isn't an iterator but looks like one, which is a recipie for disaster.

like image 28
Veedrac Avatar answered Oct 13 '22 08:10

Veedrac