summaryrefslogtreecommitdiffstats
path: root/Objects/classobject.c
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 /Objects/classobject.c
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 'Objects/classobject.c')
-rw-r--r--Objects/classobject.c40
1 files changed, 38 insertions, 2 deletions
diff --git a/Objects/classobject.c b/Objects/classobject.c
index 742e472..80b7ae5 100644
--- a/Objects/classobject.c
+++ b/Objects/classobject.c
@@ -848,7 +848,8 @@ instance_traverse(PyInstanceObject *o, visitproc visit, void *arg)
return 0;
}
-static PyObject *getitemstr, *setitemstr, *delitemstr, *lenstr, *iterstr;
+static PyObject *getitemstr, *setitemstr, *delitemstr, *lenstr;
+static PyObject *iterstr, *nextstr;
static int
instance_length(PyInstanceObject *inst)
@@ -1726,6 +1727,14 @@ instance_getiter(PyInstanceObject *self)
if ((func = instance_getattr(self, iterstr)) != NULL) {
PyObject *res = PyEval_CallObject(func, (PyObject *)NULL);
Py_DECREF(func);
+ if (res != NULL && !PyIter_Check(res)) {
+ PyErr_Format(PyExc_TypeError,
+ "__iter__ returned non-iterator "
+ "of type '%.100s'",
+ res->ob_type->tp_name);
+ Py_DECREF(res);
+ res = NULL;
+ }
return res;
}
PyErr_Clear();
@@ -1734,7 +1743,33 @@ instance_getiter(PyInstanceObject *self)
return NULL;
}
Py_DECREF(func);
- return PyIter_New((PyObject *)self);
+ return PySeqIter_New((PyObject *)self);
+}
+
+
+/* Call the iterator's next */
+static PyObject *
+instance_iternext(PyInstanceObject *self)
+{
+ PyObject *func;
+
+ if (nextstr == NULL)
+ nextstr = PyString_InternFromString("next");
+
+ if ((func = instance_getattr(self, nextstr)) != NULL) {
+ PyObject *res = PyEval_CallObject(func, (PyObject *)NULL);
+ Py_DECREF(func);
+ if (res != NULL) {
+ return res;
+ }
+ if (PyErr_ExceptionMatches(PyExc_StopIteration)) {
+ PyErr_Clear();
+ return NULL;
+ }
+ return NULL;
+ }
+ PyErr_SetString(PyExc_TypeError, "instance has no next() method");
+ return NULL;
}
@@ -1803,6 +1838,7 @@ PyTypeObject PyInstance_Type = {
instance_richcompare, /* tp_richcompare */
offsetof(PyInstanceObject, in_weakreflist), /* tp_weaklistoffset */
(getiterfunc)instance_getiter, /* tp_iter */
+ (iternextfunc)instance_iternext, /* tp_iternext */
};