[Python-Dev] Change to PyIter_Next()? (original) (raw)

Tim Peters tim.one@home.com
Fri, 4 May 2001 16:50:03 -0400


In spare moments, I've been plugging away at making various functions work nice with iterators (map, min, max, etc).

Over and over this requires writing code of the form:

op2 = PyIter_Next(it);
if (op2 == NULL) {
    /* StopIteration is *implied* by a NULL return from
     * PyIter_Next() if PyErr_Occurred() is false.
     */
    if (PyErr_Occurred()) {
        if (PyErr_ExceptionMatches(PyExc_StopIteration))
            PyErr_Clear();
        else
            goto Fail;
    }
    break;
}

This is wordy, obscure, and in my experience is needed every time I call PyIter_Next().

So I'd like to hide this in PyIter_Next instead, like so:

/* Return next item.

Then calls could be the simpler:

op2 = PyIter_Next(it, &error);
if (op2 == NULL) {
    if {error)
        goto Fail;
    break;
}

Objections? So far I'm almost the only user of PyIter_Next(); the only other use is in ceval's FOR_ITER, which goes thru a similar dance.

However, I'm not clear on why FOR_ITER doesn't clear the exception if PyErr_Occurred() and PyErr_ExceptionMatches(PyExc_StopIteration) are both true -- that sure smells like a bug (but, if so, the change above would squash it by magic).

Note that I'm not proposing to change the signature of the tp_iternext slot similarly. PyIter_Next() is a (IMO appropriately) higher-level function.