Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 14bd6de

Browse files
committed
SF 560736. Optimize list iteration by filling the tp_iter slot.
1 parent 59b2a74 commit 14bd6de

3 files changed

Lines changed: 126 additions & 18 deletions

File tree

Lib/test/test_descrtut.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ def merge(self, other):
202202
'__iadd__',
203203
'__imul__',
204204
'__init__',
205+
'__iter__',
205206
'__le__',
206207
'__len__',
207208
'__lt__',

Objects/iterobject.c

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -68,25 +68,15 @@ iter_iternext(PyObject *iterator)
6868
it = (seqiterobject *)iterator;
6969
seq = it->it_seq;
7070

71-
if (PyList_CheckExact(seq)) {
72-
PyObject *item;
73-
if (it->it_index >= PyList_GET_SIZE(seq)) {
74-
return NULL;
75-
}
76-
item = PyList_GET_ITEM(seq, it->it_index);
77-
it->it_index++;
78-
Py_INCREF(item);
79-
return item;
80-
}
8171
if (PyTuple_CheckExact(seq)) {
82-
PyObject *item;
83-
if (it->it_index >= PyTuple_GET_SIZE(seq)) {
84-
return NULL;
72+
if (it->it_index < PyTuple_GET_SIZE(seq)) {
73+
PyObject *item;
74+
item = PyTuple_GET_ITEM(seq, it->it_index);
75+
it->it_index++;
76+
Py_INCREF(item);
77+
return item;
8578
}
86-
item = PyTuple_GET_ITEM(seq, it->it_index);
87-
it->it_index++;
88-
Py_INCREF(item);
89-
return item;
79+
return NULL;
9080
}
9181
else {
9282
PyObject *result = PySequence_ITEM(seq, it->it_index);

Objects/listobject.c

Lines changed: 118 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1682,6 +1682,8 @@ static char list_doc[] =
16821682
"list() -> new list\n"
16831683
"list(sequence) -> new list initialized from sequence's items";
16841684

1685+
staticforward PyObject * list_iter(PyObject *seq);
1686+
16851687
PyTypeObject PyList_Type = {
16861688
PyObject_HEAD_INIT(&PyType_Type)
16871689
0,
@@ -1710,7 +1712,7 @@ PyTypeObject PyList_Type = {
17101712
(inquiry)list_clear, /* tp_clear */
17111713
list_richcompare, /* tp_richcompare */
17121714
0, /* tp_weaklistoffset */
1713-
0, /* tp_iter */
1715+
list_iter, /* tp_iter */
17141716
0, /* tp_iternext */
17151717
list_methods, /* tp_methods */
17161718
0, /* tp_members */
@@ -1811,3 +1813,118 @@ static PyTypeObject immutable_list_type = {
18111813
0, /* tp_init */
18121814
/* NOTE: This is *not* the standard list_type struct! */
18131815
};
1816+
1817+
1818+
/*********************** List Iterator **************************/
1819+
1820+
typedef struct {
1821+
PyObject_HEAD
1822+
long it_index;
1823+
PyObject *it_seq;
1824+
} listiterobject;
1825+
1826+
PyTypeObject PyListIter_Type;
1827+
1828+
PyObject *
1829+
list_iter(PyObject *seq)
1830+
{
1831+
listiterobject *it;
1832+
1833+
if (!PyList_Check(seq)) {
1834+
PyErr_BadInternalCall();
1835+
return NULL;
1836+
}
1837+
it = PyObject_GC_New(listiterobject, &PyListIter_Type);
1838+
if (it == NULL)
1839+
return NULL;
1840+
it->it_index = 0;
1841+
Py_INCREF(seq);
1842+
it->it_seq = seq;
1843+
_PyObject_GC_TRACK(it);
1844+
return (PyObject *)it;
1845+
}
1846+
1847+
static void
1848+
listiter_dealloc(listiterobject *it)
1849+
{
1850+
_PyObject_GC_UNTRACK(it);
1851+
Py_DECREF(it->it_seq);
1852+
PyObject_GC_Del(it);
1853+
}
1854+
1855+
static int
1856+
listiter_traverse(listiterobject *it, visitproc visit, void *arg)
1857+
{
1858+
return visit(it->it_seq, arg);
1859+
}
1860+
1861+
1862+
static PyObject *
1863+
listiter_getiter(PyObject *it)
1864+
{
1865+
Py_INCREF(it);
1866+
return it;
1867+
}
1868+
1869+
static PyObject *
1870+
listiter_next(PyObject *it)
1871+
{
1872+
PyObject *seq;
1873+
PyObject *item;
1874+
1875+
assert(PyList_Check(it));
1876+
seq = ((listiterobject *)it)->it_seq;
1877+
1878+
if (((listiterobject *)it)->it_index < PyList_GET_SIZE(seq)) {
1879+
item = ((PyListObject *)(seq))->ob_item[((listiterobject *)it)->it_index++];
1880+
Py_INCREF(item);
1881+
return item;
1882+
}
1883+
return NULL;
1884+
}
1885+
1886+
static PyMethodDef listiter_methods[] = {
1887+
{"next", (PyCFunction)listiter_next, METH_NOARGS,
1888+
"it.next() -- get the next value, or raise StopIteration"},
1889+
{NULL, NULL} /* sentinel */
1890+
};
1891+
1892+
PyTypeObject PyListIter_Type = {
1893+
PyObject_HEAD_INIT(&PyType_Type)
1894+
0, /* ob_size */
1895+
"listiterator", /* tp_name */
1896+
sizeof(listiterobject), /* tp_basicsize */
1897+
0, /* tp_itemsize */
1898+
/* methods */
1899+
(destructor)listiter_dealloc, /* tp_dealloc */
1900+
0, /* tp_print */
1901+
0, /* tp_getattr */
1902+
0, /* tp_setattr */
1903+
0, /* tp_compare */
1904+
0, /* tp_repr */
1905+
0, /* tp_as_number */
1906+
0, /* tp_as_sequence */
1907+
0, /* tp_as_mapping */
1908+
0, /* tp_hash */
1909+
0, /* tp_call */
1910+
0, /* tp_str */
1911+
PyObject_GenericGetAttr, /* tp_getattro */
1912+
0, /* tp_setattro */
1913+
0, /* tp_as_buffer */
1914+
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
1915+
0, /* tp_doc */
1916+
(traverseproc)listiter_traverse, /* tp_traverse */
1917+
0, /* tp_clear */
1918+
0, /* tp_richcompare */
1919+
0, /* tp_weaklistoffset */
1920+
(getiterfunc)listiter_getiter, /* tp_iter */
1921+
(iternextfunc)listiter_next, /* tp_iternext */
1922+
listiter_methods, /* tp_methods */
1923+
0, /* tp_members */
1924+
0, /* tp_getset */
1925+
0, /* tp_base */
1926+
0, /* tp_dict */
1927+
0, /* tp_descr_get */
1928+
0, /* tp_descr_set */
1929+
};
1930+

0 commit comments

Comments
 (0)