[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.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4