[Python-checkins] CVS: python/dist/src/Objects listobject.c,2.92.6.6,2.92.6.7
Guido van Rossum
gvanrossum@users.sourceforge.net
Wed, 06 Jun 2001 10:34:16 -0700
Update of /cvsroot/python/python/dist/src/Objects
In directory usw-pr-cvs1:/tmp/cvs-serv4094
Modified Files:
Tag: descr-branch
listobject.c
Log Message:
Make the list constructor initialize the list from an optional
'sequence' argument.
Also add a proper docstring, making this a drop-in replacement for the
built-in list() function.
Index: listobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/listobject.c,v
retrieving revision 2.92.6.6
retrieving revision 2.92.6.7
diff -C2 -r2.92.6.6 -r2.92.6.7
*** listobject.c 2001/06/06 14:27:54 2.92.6.6
--- listobject.c 2001/06/06 17:34:14 2.92.6.7
***************
*** 1497,1505 ****
}
static int
list_init(PyListObject *self, PyObject *args, PyObject *kw)
{
! self->ob_size = 0;
! self->ob_item = NULL;
return 0;
}
--- 1497,1589 ----
}
+ /* Adapted from newer code by Tim */
static int
+ list_fill(PyListObject *result, PyObject *v)
+ {
+ PyObject *it; /* iter(v) */
+ int n; /* guess for result list size */
+ int i;
+
+ n = result->ob_size;
+
+ /* Special-case list(a_list), for speed. */
+ if (PyList_Check(v)) {
+ if (v == (PyObject *)result)
+ return 0; /* source is destination, we're done */
+ return list_ass_slice(result, 0, n, v);
+ }
+
+ /* Empty previous contents */
+ if (n != 0) {
+ if (list_ass_slice(result, 0, n, (PyObject *)NULL) != 0)
+ return -1;
+ }
+
+ /* Get iterator. There may be some low-level efficiency to be gained
+ * by caching the tp_iternext slot instead of using PyIter_Next()
+ * later, but premature optimization is the root etc.
+ */
+ it = PyObject_GetIter(v);
+ if (it == NULL)
+ return -1;
+
+ /* Guess a result list size. */
+ n = -1; /* unknown */
+ if (PySequence_Check(v) &&
+ v->ob_type->tp_as_sequence->sq_length) {
+ n = PySequence_Size(v);
+ if (n < 0)
+ PyErr_Clear();
+ }
+ if (n < 0)
+ n = 8; /* arbitrary */
+ NRESIZE(result->ob_item, PyObject*, n);
+ if (result->ob_item == NULL)
+ goto error;
+ result->ob_size = n;
+
+ /* Run iterator to exhaustion. */
+ for (i = 0; ; i++) {
+ PyObject *item = PyIter_Next(it);
+ if (item == NULL) {
+ if (PyErr_Occurred())
+ goto error;
+ break;
+ }
+ if (i < n)
+ PyList_SET_ITEM(result, i, item); /* steals ref */
+ else {
+ int status = ins1(result, result->ob_size, item);
+ Py_DECREF(item); /* append creates a new ref */
+ if (status < 0)
+ goto error;
+ }
+ }
+
+ /* Cut back result list if initial guess was too large. */
+ if (i < n && result != NULL) {
+ if (list_ass_slice(result, i, n, (PyObject *)NULL) != 0)
+ goto error;
+ }
+ Py_DECREF(it);
+ return 0;
+
+ error:
+ Py_DECREF(it);
+ return -1;
+ }
+
+ static int
list_init(PyListObject *self, PyObject *args, PyObject *kw)
{
! PyObject *arg = NULL;
! static char *kwlist[] = {"sequence", 0};
!
! if (!PyArg_ParseTupleAndKeywords(args, kw, "|O:list", kwlist, &arg))
! return -1;
! if (arg != NULL)
! return list_fill(self, arg);
! if (self->ob_size > 0)
! return list_ass_slice(self, 0, self->ob_size, (PyObject*)NULL);
return 0;
}
***************
*** 1550,1553 ****
--- 1634,1641 ----
};
+ static char list_doc[] =
+ "list() -> new list\n"
+ "list(sequence) -> new list initialized from sequence's items";
+
PyTypeObject PyList_Type = {
PyObject_HEAD_INIT(&PyType_Type)
***************
*** 1572,1576 ****
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /* tp_flags */
! 0, /* tp_doc */
(traverseproc)list_traverse, /* tp_traverse */
(inquiry)list_clear, /* tp_clear */
--- 1660,1664 ----
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /* tp_flags */
! list_doc, /* tp_doc */
(traverseproc)list_traverse, /* tp_traverse */
(inquiry)list_clear, /* tp_clear */
***************
*** 1658,1662 ****
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /* tp_flags */
! 0, /* tp_doc */
(traverseproc)list_traverse, /* tp_traverse */
0, /* tp_clear */
--- 1746,1750 ----
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /* tp_flags */
! list_doc, /* tp_doc */
(traverseproc)list_traverse, /* tp_traverse */
0, /* tp_clear */