Skip to content

Commit 0b43d19

Browse files
author
rhettinger
committed
Optimize reversed(list) using a custom iterator.
git-svn-id: http://svn.python.org/projects/python/trunk@34592 6015fed2-1504-0410-9fe1-9d1591cc4771
1 parent aaabdb9 commit 0b43d19

File tree

2 files changed

+98
-4
lines changed

2 files changed

+98
-4
lines changed

Objects/enumobject.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -174,8 +174,8 @@ reversed_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
174174
if (!PyArg_UnpackTuple(args, "reversed", 1, 1, &seq))
175175
return NULL;
176176

177-
/* Special case optimization for xrange */
178-
if (PyRange_Check(seq))
177+
/* Special case optimization for xrange and lists */
178+
if (PyRange_Check(seq) || PyList_Check(seq))
179179
return PyObject_CallMethod(seq, "__reversed__", NULL);
180180

181181
if (!PySequence_Check(seq)) {

Objects/listobject.c

Lines changed: 96 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2349,6 +2349,11 @@ list_nohash(PyObject *self)
23492349
return -1;
23502350
}
23512351

2352+
static PyObject *list_iter(PyObject *seq);
2353+
static PyObject *list_reversed(PyListObject* seq, PyObject* unused);
2354+
2355+
PyDoc_STRVAR(reversed_doc,
2356+
"L.__reversed__() -- return a reverse iterator over the list");
23522357
PyDoc_STRVAR(append_doc,
23532358
"L.append(object) -- append object to end");
23542359
PyDoc_STRVAR(extend_doc,
@@ -2373,6 +2378,7 @@ PyDoc_STRVAR(sorted_doc,
23732378
cmp(x, y) -> -1, 0, 1");
23742379

23752380
static PyMethodDef list_methods[] = {
2381+
{"__reversed__",(PyCFunction)list_reversed, METH_NOARGS, reversed_doc},
23762382
{"append", (PyCFunction)listappend, METH_O, append_doc},
23772383
{"insert", (PyCFunction)listinsert, METH_VARARGS, insert_doc},
23782384
{"extend", (PyCFunction)listextend, METH_O, extend_doc},
@@ -2404,8 +2410,6 @@ PyDoc_STRVAR(list_doc,
24042410
"list() -> new list\n"
24052411
"list(sequence) -> new list initialized from sequence's items");
24062412

2407-
static PyObject *list_iter(PyObject *seq);
2408-
24092413
static PyObject *
24102414
list_subscript(PyListObject* self, PyObject* item)
24112415
{
@@ -2760,3 +2764,93 @@ PyTypeObject PyListIter_Type = {
27602764
0, /* tp_descr_get */
27612765
0, /* tp_descr_set */
27622766
};
2767+
2768+
/*********************** List Reverse Iterator **************************/
2769+
2770+
typedef struct {
2771+
PyObject_HEAD
2772+
long it_index;
2773+
PyListObject *it_seq;
2774+
} listreviterobject;
2775+
2776+
PyTypeObject PyListRevIter_Type;
2777+
2778+
static PyObject *
2779+
list_reversed(PyListObject *seq, PyObject *unused)
2780+
{
2781+
listreviterobject *it;
2782+
2783+
it = PyObject_GC_New(listreviterobject, &PyListRevIter_Type);
2784+
if (it == NULL)
2785+
return NULL;
2786+
assert(PyList_Check(seq));
2787+
it->it_index = PyList_GET_SIZE(seq) - 1;
2788+
Py_INCREF(seq);
2789+
it->it_seq = seq;
2790+
PyObject_GC_Track(it);
2791+
return (PyObject *)it;
2792+
}
2793+
2794+
static void
2795+
listreviter_dealloc(listreviterobject *it)
2796+
{
2797+
PyObject_GC_UnTrack(it);
2798+
Py_XDECREF(it->it_seq);
2799+
PyObject_GC_Del(it);
2800+
}
2801+
2802+
static int
2803+
listreviter_traverse(listreviterobject *it, visitproc visit, void *arg)
2804+
{
2805+
if (it->it_seq == NULL)
2806+
return 0;
2807+
return visit((PyObject *)it->it_seq, arg);
2808+
}
2809+
2810+
static PyObject *
2811+
listreviter_next(listreviterobject *it)
2812+
{
2813+
PyObject *item = NULL;
2814+
2815+
assert(PyList_Check(it->it_seq));
2816+
if (it->it_index >= 0) {
2817+
assert(it->it_index < PyList_GET_SIZE(it->it_seq));
2818+
item = PyList_GET_ITEM(it->it_seq, it->it_index);
2819+
it->it_index--;
2820+
Py_INCREF(item);
2821+
}
2822+
return item;
2823+
}
2824+
2825+
PyTypeObject PyListRevIter_Type = {
2826+
PyObject_HEAD_INIT(&PyType_Type)
2827+
0, /* ob_size */
2828+
"listreverseiterator", /* tp_name */
2829+
sizeof(listreviterobject), /* tp_basicsize */
2830+
0, /* tp_itemsize */
2831+
/* methods */
2832+
(destructor)listreviter_dealloc, /* tp_dealloc */
2833+
0, /* tp_print */
2834+
0, /* tp_getattr */
2835+
0, /* tp_setattr */
2836+
0, /* tp_compare */
2837+
0, /* tp_repr */
2838+
0, /* tp_as_number */
2839+
0, /* tp_as_sequence */
2840+
0, /* tp_as_mapping */
2841+
0, /* tp_hash */
2842+
0, /* tp_call */
2843+
0, /* tp_str */
2844+
PyObject_GenericGetAttr, /* tp_getattro */
2845+
0, /* tp_setattro */
2846+
0, /* tp_as_buffer */
2847+
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
2848+
0, /* tp_doc */
2849+
(traverseproc)listreviter_traverse, /* tp_traverse */
2850+
0, /* tp_clear */
2851+
0, /* tp_richcompare */
2852+
0, /* tp_weaklistoffset */
2853+
PyObject_SelfIter, /* tp_iter */
2854+
(iternextfunc)listreviter_next, /* tp_iternext */
2855+
0,
2856+
};

0 commit comments

Comments
 (0)