diff options
author | Guido van Rossum <guido@python.org> | 2001-04-23 14:08:49 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 2001-04-23 14:08:49 (GMT) |
commit | 213c7a6aa5889f42495352199715a1c1a0833a00 (patch) | |
tree | 7559cd072f732c861cb28adb7192561a877fd6fb /Python/ceval.c | |
parent | 8b3d6ca3df1097752a1091b2c8f6d7de1b36a81d (diff) | |
download | cpython-213c7a6aa5889f42495352199715a1c1a0833a00.zip cpython-213c7a6aa5889f42495352199715a1c1a0833a00.tar.gz cpython-213c7a6aa5889f42495352199715a1c1a0833a00.tar.bz2 |
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.
Diffstat (limited to 'Python/ceval.c')
-rw-r--r-- | Python/ceval.c | 43 |
1 files changed, 16 insertions, 27 deletions
diff --git a/Python/ceval.c b/Python/ceval.c index d76c6f2..d5e3a4e 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -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: ... |