Mercurial > cpython-lru_cache-weakref
diff Python/ceval.c @ 17617:aac65f50df6f legacy-trunk
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.
| author | Guido van Rossum <guido@python.org> |
|---|---|
| date | Mon, 23 Apr 2001 14:08:49 +0000 |
| parents | 1fe8e50e6e1b |
| children | 9921a9d27f72 |
line wrap: on
line diff
--- a/Python/ceval.c Mon Apr 23 13:22:59 2001 +0000 +++ b/Python/ceval.c Mon Apr 23 14:08:49 2001 +0000 @@ -381,7 +381,6 @@ /* 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 @@ 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 @@ 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: ...
