Mondo changes to the iterator stuff, without changing how Python code

sees it (test_iter.py is unchanged).

- Added a tp_iternext slot, which calls the iterator's next() method;
  this is much faster for built-in iterators over built-in types
  such as lists and dicts, speeding up pybench's ForLoop with about
  25% compared to Python 2.1.  (Now there's a good argument for
  iterators. ;-)

- Renamed the built-in sequence iterator SeqIter, affecting the C API
  functions for it.  (This frees up the PyIter prefix for generic
  iterator operations.)

- Added PyIter_Check(obj), which checks that obj's type has a
  tp_iternext slot and that the proper feature flag is set.

- Added PyIter_Next(obj) which calls the tp_iternext slot.  It has a
  somewhat complex return condition due to the need for speed: when it
  returns NULL, it may not have set an exception condition, meaning
  the iterator is exhausted; when the exception StopIteration is set
  (or a derived exception class), it means the same thing; any other
  exception means some other error occurred.
This commit is contained in:
Guido van Rossum 2001-04-23 14:08:49 +00:00
parent 8b3d6ca3df
commit 213c7a6aa5
9 changed files with 188 additions and 64 deletions

View file

@ -381,7 +381,6 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals,
/* Make it easier to find out where we are with a debugger */
char *filename = PyString_AsString(co->co_filename);
#endif
static PyObject *nextstr;
/* Code access macros */
@ -417,11 +416,6 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals,
GETLOCAL(i) = value; } while (0)
/* Start of code */
if (nextstr == NULL) {
nextstr = PyString_InternFromString("next");
if (nextstr == NULL)
return NULL;
}
#ifdef USE_STACKCHECK
if (tstate->recursion_depth%10 == 0 && PyOS_CheckStack()) {
@ -1887,34 +1881,29 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals,
x = PyObject_GetIter(v);
Py_DECREF(v);
if (x != NULL) {
w = x;
x = PyObject_GetAttr(w, nextstr);
Py_DECREF(w);
if (x != NULL) {
PUSH(x);
continue;
}
PUSH(x);
continue;
}
break;
case FOR_ITER:
/* before: [iter]; after: [iter, iter()] *or* [] */
v = TOP();
x = PyObject_CallObject(v, NULL);
if (x == NULL) {
if (PyErr_ExceptionMatches(
PyExc_StopIteration))
{
PyErr_Clear();
x = v = POP();
Py_DECREF(v);
JUMPBY(oparg);
continue;
}
break;
x = PyIter_Next(v);
if (x != NULL) {
PUSH(x);
continue;
}
PUSH(x);
continue;
if (!PyErr_Occurred() ||
PyErr_ExceptionMatches(
PyExc_StopIteration))
{
x = v = POP();
Py_DECREF(v);
JUMPBY(oparg);
continue;
}
break;
case FOR_LOOP:
/* for v in s: ...