[Python-Dev] Termination of two-arg iter()
Tim Peters
tim.one@comcast.net
Tue, 16 Jul 2002 01:56:33 -0400
[Guido]
> While preparing a patch, I discovered something strange: despite the
> fact that listiter_next() never raises StopIteration when it returns
> NULL,
That much is a documented part of the tp_iternext protocol.
> and despite the fact that it is used as the implementation for
> the next() method,
Oops.
> calling iter(list()).next() *does* raise StopIteration, rather than a
> complaint about NULL without setting an exception condition.
That is surprising!
> It took a brief debugging session to discover that in the presence
> of a tp_iternext function, the type machinery adds a next method that
> wraps tp_iternext. Cute, though unexpected!
It also explains an old mystery I never got around to investigating:
>>> print iter([]).next.__doc__
x.next() -> the next value, or raise StopIteration
>>>
That was a mystery because that's not the docstring attached to the list
iterator's next() method:
static PyMethodDef listiter_methods[] = {
{"next", (PyCFunction)listiter_next, METH_NOARGS,
"it.next() -- get the next value, or raise StopIteration"},
> It means that the implementation of various iterators can be a little
> simpler, because no next() implementation needs to be given.
I'm not sure that's a feature we always want to use. Going thru a wrapper
function (a) adds another layer of function call, and (b) adds a
if (!PyArg_ParseTuple(args, ""))
return NULL;
call via wrap_next(). Both expenses could be avoided if an existing next
method were left alone. I suppose only the seoond expense is actually
"real", though, as most explicit xyz_next methods naturally call the
tp_iternext slot function anyway. Still, when the body of a "next" method
is as simple as it is for lists, a call to PyArg_ParseTuple is a significant
overhead.