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/abstract.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/abstract.c')
-rw-r--r-- | Objects/abstract.c | 28 |
1 files changed, 25 insertions, 3 deletions
diff --git a/Objects/abstract.c b/Objects/abstract.c index 8a6df76..f656747 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -1748,10 +1748,32 @@ PyObject_GetIter(PyObject *o) f = t->tp_iter; if (f == NULL) { if (PySequence_Check(o)) - return PyIter_New(o); + return PySeqIter_New(o); PyErr_SetString(PyExc_TypeError, "iter() of non-sequence"); return NULL; } - else - return (*f)(o); + else { + PyObject *res = (*f)(o); + 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; + } +} + +PyObject * +PyIter_Next(PyObject *iter) +{ + if (!PyIter_Check(iter)) { + PyErr_Format(PyExc_TypeError, + "'%.100s' object is not an iterator", + iter->ob_type->tp_name); + return NULL; + } + return (*iter->ob_type->tp_iternext)(iter); } |