[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 */