5

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.

1
  • any next() will affect all others Commented Feb 26, 2015 at 14:34

2 Answers 2

3

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
Sign up to request clarification or add additional context in comments.

1 Comment

Wasn't as straightforward as I thought. I guess I got to move the answered mark. :-)
1

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.