diff options
author | Guido van Rossum <guido@python.org> | 2001-04-23 14:08:49 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 2001-04-23 14:08:49 (GMT) |
commit | 213c7a6aa5889f42495352199715a1c1a0833a00 (patch) | |
tree | 7559cd072f732c861cb28adb7192561a877fd6fb /Objects/dictobject.c | |
parent | 8b3d6ca3df1097752a1091b2c8f6d7de1b36a81d (diff) | |
download | cpython-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.c | 23 |
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 */ }; |