summaryrefslogtreecommitdiffstats
path: root/Objects/dictobject.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/dictobject.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/dictobject.c')
-rw-r--r--Objects/dictobject.c23
1 files changed, 21 insertions, 2 deletions
diff --git a/Objects/dictobject.c b/Objects/dictobject.c
index 17b6a04..9a24109 100644
--- a/Objects/dictobject.c
+++ b/Objects/dictobject.c
@@ -1354,6 +1354,7 @@ PyTypeObject PyDict_Type = {
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
(getiterfunc)dictiter_new, /* tp_iter */
+ 0, /* tp_iternext */
};
/* For backward compatibility with old dictionary interface */
@@ -1433,6 +1434,7 @@ static PyObject *
dictiter_next(dictiterobject *di, PyObject *args)
{
PyObject *key;
+
if (di->di_size != di->di_dict->ma_size) {
PyErr_SetString(PyExc_RuntimeError,
"dictionary changed size during iteration");
@@ -1460,9 +1462,25 @@ static PyMethodDef dictiter_methods[] = {
};
static PyObject *
-dictiter_getattr(dictiterobject *it, char *name)
+dictiter_getattr(dictiterobject *di, char *name)
+{
+ return Py_FindMethod(dictiter_methods, (PyObject *)di, name);
+}
+
+static PyObject *dictiter_iternext(dictiterobject *di)
{
- return Py_FindMethod(dictiter_methods, (PyObject *)it, name);
+ PyObject *key;
+
+ if (di->di_size != di->di_dict->ma_size) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "dictionary changed size during iteration");
+ return NULL;
+ }
+ if (PyDict_Next((PyObject *)(di->di_dict), &di->di_pos, &key, NULL)) {
+ Py_INCREF(key);
+ return key;
+ }
+ return NULL;
}
PyTypeObject PyDictIter_Type = {
@@ -1494,4 +1512,5 @@ PyTypeObject PyDictIter_Type = {
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
(getiterfunc)dictiter_getiter, /* tp_iter */
+ (iternextfunc)dictiter_iternext, /* tp_iternext */
};