Skip to content

Commit 8ca92ae

Browse files
committed
Eliminate a big block of duplicate code in PySequence_List() by
exposing _PyList_Extend().
1 parent 97bc618 commit 8ca92ae

3 files changed

Lines changed: 13 additions & 54 deletions

File tree

Include/listobject.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ PyAPI_FUNC(int) PyList_SetSlice(PyObject *, int, int, PyObject *);
4141
PyAPI_FUNC(int) PyList_Sort(PyObject *);
4242
PyAPI_FUNC(int) PyList_Reverse(PyObject *);
4343
PyAPI_FUNC(PyObject *) PyList_AsTuple(PyObject *);
44+
PyAPI_FUNC(PyObject *) _PyList_Extend(PyListObject *, PyObject *);
4445

4546
/* Macro, trading safety for speed */
4647
#define PyList_GET_ITEM(op, i) (((PyListObject *)(op))->ob_item[i])

Objects/abstract.c

Lines changed: 6 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1427,69 +1427,21 @@ PySequence_Tuple(PyObject *v)
14271427
PyObject *
14281428
PySequence_List(PyObject *v)
14291429
{
1430-
PyObject *it; /* iter(v) */
14311430
PyObject *result; /* result list */
1432-
int n; /* guess for result list size */
1433-
int i;
1431+
PyObject *rv; /* return value from PyList_Extend */
14341432

14351433
if (v == NULL)
14361434
return null_error();
14371435

1438-
/* Special-case list(a_list), for speed. */
1439-
if (PyList_Check(v))
1440-
return PyList_GetSlice(v, 0, PyList_GET_SIZE(v));
1441-
1442-
/* Get iterator. There may be some low-level efficiency to be gained
1443-
* by caching the tp_iternext slot instead of using PyIter_Next()
1444-
* later, but premature optimization is the root etc.
1445-
*/
1446-
it = PyObject_GetIter(v);
1447-
if (it == NULL)
1436+
result = PyList_New(0);
1437+
if (result == NULL)
14481438
return NULL;
14491439

1450-
/* Guess a result list size. */
1451-
n = PyObject_Size(v);
1452-
if (n < 0) {
1453-
PyErr_Clear();
1454-
n = 8; /* arbitrary */
1455-
}
1456-
result = PyList_New(n);
1457-
if (result == NULL) {
1458-
Py_DECREF(it);
1440+
rv = _PyList_Extend((PyListObject *)result, v);
1441+
if (rv == NULL) {
1442+
Py_DECREF(result);
14591443
return NULL;
14601444
}
1461-
1462-
/* Run iterator to exhaustion. */
1463-
for (i = 0; ; i++) {
1464-
PyObject *item = PyIter_Next(it);
1465-
if (item == NULL) {
1466-
if (PyErr_Occurred()) {
1467-
Py_DECREF(result);
1468-
result = NULL;
1469-
}
1470-
break;
1471-
}
1472-
if (i < n)
1473-
PyList_SET_ITEM(result, i, item); /* steals ref */
1474-
else {
1475-
int status = PyList_Append(result, item);
1476-
Py_DECREF(item); /* append creates a new ref */
1477-
if (status < 0) {
1478-
Py_DECREF(result);
1479-
result = NULL;
1480-
break;
1481-
}
1482-
}
1483-
}
1484-
1485-
/* Cut back result list if initial guess was too large. */
1486-
if (i < n && result != NULL) {
1487-
if (PyList_SetSlice(result, i, n, (PyObject *)NULL) != 0) {
1488-
Py_DECREF(result);
1489-
result = NULL;
1490-
}
1491-
}
1492-
Py_DECREF(it);
14931445
return result;
14941446
}
14951447

Objects/listobject.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -776,6 +776,12 @@ listextend(PyListObject *self, PyObject *b)
776776
return NULL;
777777
}
778778

779+
PyObject *
780+
_PyList_Extend(PyListObject *self, PyObject *b)
781+
{
782+
return listextend(self, b);
783+
}
784+
779785
static PyObject *
780786
list_inplace_concat(PyListObject *self, PyObject *other)
781787
{

0 commit comments

Comments
 (0)