mirror of
https://github.com/python/cpython.git
synced 2025-09-15 21:26:04 +00:00
Iterators phase 1. This comprises:
new slot tp_iter in type object, plus new flag Py_TPFLAGS_HAVE_ITER new C API PyObject_GetIter(), calls tp_iter new builtin iter(), with two forms: iter(obj), and iter(function, sentinel) new internal object types iterobject and calliterobject new exception StopIteration new opcodes for "for" loops, GET_ITER and FOR_ITER (also supported by dis.py) new magic number for .pyc files new special method for instances: __iter__() returns an iterator iteration over dictionaries: "for x in dict" iterates over the keys iteration over files: "for x in file" iterates over lines TODO: documentation test suite decide whether to use a different way to spell iter(function, sentinal) decide whether "for key in dict" is a good idea use iterators in map/filter/reduce, min/max, and elsewhere (in/not in?) speed tuning (make next() a slot tp_next???)
This commit is contained in:
parent
12e73bb2f0
commit
59d1d2b434
16 changed files with 256 additions and 25 deletions
|
@ -381,6 +381,7 @@ 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 */
|
||||
|
||||
|
@ -416,6 +417,11 @@ 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()) {
|
||||
|
@ -1875,6 +1881,41 @@ eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals,
|
|||
JUMPTO(oparg);
|
||||
continue;
|
||||
|
||||
case GET_ITER:
|
||||
/* before: [obj]; after [getiter(obj)] */
|
||||
v = POP();
|
||||
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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
PUSH(x);
|
||||
continue;
|
||||
|
||||
case FOR_LOOP:
|
||||
/* for v in s: ...
|
||||
On entry: stack contains s, i.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue