mirror of
https://github.com/python/cpython.git
synced 2025-08-30 21:48:47 +00:00
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:
parent
8b3d6ca3df
commit
213c7a6aa5
9 changed files with 188 additions and 64 deletions
|
@ -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: ...
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue