summaryrefslogtreecommitdiffstats
path: root/Python
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>2001-04-23 14:08:49 (GMT)
committerGuido van Rossum <guido@python.org>2001-04-23 14:08:49 (GMT)
commit213c7a6aa5889f42495352199715a1c1a0833a00 (patch)
tree7559cd072f732c861cb28adb7192561a877fd6fb /Python
parent8b3d6ca3df1097752a1091b2c8f6d7de1b36a81d (diff)
downloadcpython-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')
-rw-r--r--Python/ceval.c43
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: ...