[Python-checkins] python/dist/src/Modules itertoolsmodule.c,1.5,1.6

rhettinger@users.sourceforge.net rhettinger@users.sourceforge.net
2003年2月22日 20:40:09 -0800


Update of /cvsroot/python/python/dist/src/Modules
In directory sc8-pr-cvs1:/tmp/cvs-serv23087/Modules
Modified Files:
	itertoolsmodule.c 
Log Message:
User requested changes to the itertools module.
Subsumed times() into repeat(). 
Added cycle() and chain().
Index: itertoolsmodule.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Modules/itertoolsmodule.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -C2 -d -r1.5 -r1.6
*** itertoolsmodule.c	9 Feb 2003 17:18:42 -0000	1.5
--- itertoolsmodule.c	23 Feb 2003 04:40:07 -0000	1.6
***************
*** 8,11 ****
--- 8,168 ----
 */
 
+ /* cycle object **********************************************************/
+ 
+ typedef struct {
+ 	PyObject_HEAD
+ 	PyObject *it;
+ 	PyObject *saved;
+ 	int firstpass;
+ } cycleobject;
+ 
+ PyTypeObject cycle_type;
+ 
+ static PyObject *
+ cycle_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+ {
+ 	PyObject *it;
+ 	PyObject *iterable;
+ 	PyObject *saved;
+ 	cycleobject *lz;
+ 
+ 	if (!PyArg_UnpackTuple(args, "cycle", 1, 1, &iterable))
+ 		return NULL;
+ 
+ 	/* Get iterator. */
+ 	it = PyObject_GetIter(iterable);
+ 	if (it == NULL)
+ 		return NULL;
+ 
+ 	saved = PyList_New(0);
+ 	if (saved == NULL) {
+ 		Py_DECREF(it);
+ 		return NULL;
+ 	}
+ 
+ 	/* create cycleobject structure */
+ 	lz = (cycleobject *)type->tp_alloc(type, 0);
+ 	if (lz == NULL) {
+ 		Py_DECREF(it);
+ 		Py_DECREF(saved);
+ 		return NULL;
+ 	}
+ 	lz->it = it;
+ 	lz->saved = saved;
+ 	lz->firstpass = 0;
+ 
+ 	return (PyObject *)lz;
+ }
+ 
+ static void
+ cycle_dealloc(cycleobject *lz)
+ {
+ 	PyObject_GC_UnTrack(lz);
+ 	Py_XDECREF(lz->saved);
+ 	Py_XDECREF(lz->it);
+ 	lz->ob_type->tp_free(lz);
+ }
+ 
+ static int
+ cycle_traverse(cycleobject *lz, visitproc visit, void *arg)
+ {
+ 	int err;
+ 
+ 	if (lz->it) {
+ 		err = visit(lz->it, arg);
+ 		if (err)
+ 			return err;
+ 	}
+ 	if (lz->saved) {
+ 		err = visit(lz->saved, arg);
+ 		if (err)
+ 			return err;
+ 	}
+ 	return 0;
+ }
+ 
+ static PyObject *
+ cycle_next(cycleobject *lz)
+ {
+ 	PyObject *item;
+ 	PyObject *it;
+ 
+ 	while (1) {
+ 		item = PyIter_Next(lz->it);
+ 		if (item != NULL) {
+ 			if (!lz->firstpass)
+ 				PyList_Append(lz->saved, item);
+ 			return item;
+ 		}
+ 		if (PyList_Size(lz->saved) == 0) 
+ 			return NULL;
+ 		it = PyObject_GetIter(lz->saved);
+ 		if (it == NULL)
+ 			return NULL;
+ 		Py_DECREF(lz->it);
+ 		lz->it = it;
+ 		lz->firstpass = 1;
+ 	}
+ }
+ 
+ static PyObject *
+ cycle_getiter(PyObject *lz)
+ {
+ 	Py_INCREF(lz);
+ 	return lz;
+ }
+ 
+ PyDoc_STRVAR(cycle_doc,
+ "cycle(iterable) --> cycle object\n\
+ \n\
+ Return elements from the iterable until it is exhausted.\n\
+ Then repeat the sequence indefinitely.");
+ 
+ PyTypeObject cycle_type = {
+ 	PyObject_HEAD_INIT(NULL)
+ 	0,				/* ob_size */
+ 	"itertools.cycle",		/* tp_name */
+ 	sizeof(cycleobject),		/* tp_basicsize */
+ 	0,				/* tp_itemsize */
+ 	/* methods */
+ 	(destructor)cycle_dealloc,	/* tp_dealloc */
+ 	0,				/* tp_print */
+ 	0,				/* tp_getattr */
+ 	0,				/* tp_setattr */
+ 	0,				/* tp_compare */
+ 	0,				/* tp_repr */
+ 	0,				/* tp_as_number */
+ 	0,				/* tp_as_sequence */
+ 	0,				/* tp_as_mapping */
+ 	0,				/* tp_hash */
+ 	0,				/* tp_call */
+ 	0,				/* tp_str */
+ 	PyObject_GenericGetAttr,	/* tp_getattro */
+ 	0,				/* tp_setattro */
+ 	0,				/* tp_as_buffer */
+ 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
+ 		Py_TPFLAGS_BASETYPE,	/* tp_flags */
+ 	cycle_doc,			/* tp_doc */
+ 	(traverseproc)cycle_traverse,	/* tp_traverse */
+ 	0,				/* tp_clear */
+ 	0,				/* tp_richcompare */
+ 	0,				/* tp_weaklistoffset */
+ 	(getiterfunc)cycle_getiter,	/* tp_iter */
+ 	(iternextfunc)cycle_next,	/* tp_iternext */
+ 	0,				/* tp_methods */
+ 	0,				/* tp_members */
+ 	0,				/* tp_getset */
+ 	0,				/* tp_base */
+ 	0,				/* tp_dict */
+ 	0,				/* tp_descr_get */
+ 	0,				/* tp_descr_set */
+ 	0,				/* tp_dictoffset */
+ 	0,				/* tp_init */
+ 	PyType_GenericAlloc,		/* tp_alloc */
+ 	cycle_new,			/* tp_new */
+ 	PyObject_GC_Del,		/* tp_free */
+ };
+ 
+ 
 /* dropwhile object **********************************************************/
 
***************
*** 827,863 ****
 
 
! /* times object ************************************************************/
 
 typedef struct {
 	PyObject_HEAD
! 	PyObject *obj;
! 	long	cnt;
! } timesobject;
 
! PyTypeObject times_type;
 
 static PyObject *
! times_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
! 	timesobject *lz;
! 	PyObject *obj = Py_None;
! 	long cnt;
! 
! 	if (!PyArg_ParseTuple(args, "l|O:times", &cnt, &obj))
! 		return NULL;
 
! 	if (cnt < 0) {
! 		PyErr_SetString(PyExc_ValueError,
! 		 "count for times() cannot be negative.");
 		return NULL;
 	}
 
! 	/* create timesobject structure */
! 	lz = (timesobject *)type->tp_alloc(type, 0);
 	if (lz == NULL)
 		return NULL;
! 	lz->cnt = cnt;
! 	Py_INCREF(obj);
! 	lz->obj = obj;
 
 	return (PyObject *)lz;
--- 984,1033 ----
 
 
! /* chain object ************************************************************/
 
 typedef struct {
 	PyObject_HEAD
! 	long	tuplesize;
! 	long	iternum;		/* which iterator is active */
! 	PyObject *ittuple;		/* tuple of iterators */
! } chainobject;
 
! PyTypeObject chain_type;
 
 static PyObject *
! chain_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
! 	chainobject *lz;
! 	int tuplesize = PySequence_Length(args);
! 	int i;
! 	PyObject *ittuple;
 
! 	/* obtain iterators */
! 	assert(PyTuple_Check(args));
! 	ittuple = PyTuple_New(tuplesize);
! 	if(ittuple == NULL)
 		return NULL;
+ 	for (i=0; i < tuplesize; ++i) {
+ 		PyObject *item = PyTuple_GET_ITEM(args, i);
+ 		PyObject *it = PyObject_GetIter(item);
+ 		if (it == NULL) {
+ 			if (PyErr_ExceptionMatches(PyExc_TypeError))
+ 				PyErr_Format(PyExc_TypeError,
+ 				 "chain argument #%d must support iteration",
+ 				 i+1);
+ 			Py_DECREF(ittuple);
+ 			return NULL;
+ 		}
+ 		PyTuple_SET_ITEM(ittuple, i, it);
 	}
 
! 	/* create chainobject structure */
! 	lz = (chainobject *)type->tp_alloc(type, 0);
 	if (lz == NULL)
 		return NULL;
! 
! 	lz->ittuple = ittuple;
! 	lz->iternum = 0;
! 	lz->tuplesize = tuplesize;
 
 	return (PyObject *)lz;
***************
*** 865,892 ****
 
 static void
! times_dealloc(timesobject *lz)
 {
 	PyObject_GC_UnTrack(lz);
! 	Py_XDECREF(lz->obj);
 	lz->ob_type->tp_free(lz);
 }
 
 static int
! times_traverse(timesobject *lz, visitproc visit, void *arg)
 {
! 	if (lz->obj)
! 		return visit(lz->obj, arg);
 	return 0;
 }
 
 static PyObject *
! times_next(timesobject *lz)
 {
! 	PyObject *obj = lz->obj;
 
! 	if (lz->cnt > 0) {
! 		lz->cnt--;
! 		Py_INCREF(obj);
! 		return obj;
 	}
 	return NULL;
--- 1035,1065 ----
 
 static void
! chain_dealloc(chainobject *lz)
 {
 	PyObject_GC_UnTrack(lz);
! 	Py_XDECREF(lz->ittuple);
 	lz->ob_type->tp_free(lz);
 }
 
 static int
! chain_traverse(chainobject *lz, visitproc visit, void *arg)
 {
! 	if (lz->ittuple)
! 		return visit(lz->ittuple, arg);
 	return 0;
 }
 
 static PyObject *
! chain_next(chainobject *lz)
 {
! 	PyObject *it;
! 	PyObject *item;
 
! 	while (lz->iternum < lz->tuplesize) {
! 		it = PyTuple_GET_ITEM(lz->ittuple, lz->iternum);
! 		item = PyIter_Next(it);
! 		if (item != NULL)
! 			return item;
! 		lz->iternum++;
 	}
 	return NULL;
***************
*** 894,898 ****
 
 static PyObject *
! times_getiter(PyObject *lz)
 {
 	Py_INCREF(lz);
--- 1067,1071 ----
 
 static PyObject *
! chain_getiter(PyObject *lz)
 {
 	Py_INCREF(lz);
***************
*** 900,917 ****
 }
 
! PyDoc_STRVAR(times_doc,
! "times(n [,obj]) --> times object\n\
 \n\
! Return a times object whose .next() method returns n consecutive\n\
! instances of obj (default is None).");
 
! PyTypeObject times_type = {
 	PyObject_HEAD_INIT(NULL)
 	0,				/* ob_size */
! 	"itertools.times",		/* tp_name */
! 	sizeof(timesobject),		/* tp_basicsize */
 	0,				/* tp_itemsize */
 	/* methods */
! 	(destructor)times_dealloc,	/* tp_dealloc */
 	0,				/* tp_print */
 	0,				/* tp_getattr */
--- 1073,1091 ----
 }
 
! PyDoc_STRVAR(chain_doc,
! "chain(*iterables) --> chain object\n\
 \n\
! Return a chain object whose .next() method returns elements from the\n\
! first iterable until it is exhausted, then elements from the next\n\
! iterable, until all of the iterables are exhausted.");
 
! PyTypeObject chain_type = {
 	PyObject_HEAD_INIT(NULL)
 	0,				/* ob_size */
! 	"itertools.chain",		/* tp_name */
! 	sizeof(chainobject),		/* tp_basicsize */
 	0,				/* tp_itemsize */
 	/* methods */
! 	(destructor)chain_dealloc,	/* tp_dealloc */
 	0,				/* tp_print */
 	0,				/* tp_getattr */
***************
*** 930,940 ****
 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
 		Py_TPFLAGS_BASETYPE,	/* tp_flags */
! 	times_doc,			/* tp_doc */
! 	(traverseproc)times_traverse,	/* tp_traverse */
 	0,				/* tp_clear */
 	0,				/* tp_richcompare */
 	0,				/* tp_weaklistoffset */
! 	(getiterfunc)times_getiter,	/* tp_iter */
! 	(iternextfunc)times_next,	/* tp_iternext */
 	0,				/* tp_methods */
 	0,				/* tp_members */
--- 1104,1114 ----
 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
 		Py_TPFLAGS_BASETYPE,	/* tp_flags */
! 	chain_doc,			/* tp_doc */
! 	(traverseproc)chain_traverse,	/* tp_traverse */
 	0,				/* tp_clear */
 	0,				/* tp_richcompare */
 	0,				/* tp_weaklistoffset */
! 	(getiterfunc)chain_getiter,	/* tp_iter */
! 	(iternextfunc)chain_next,	/* tp_iternext */
 	0,				/* tp_methods */
 	0,				/* tp_members */
***************
*** 947,951 ****
 	0,				/* tp_init */
 	PyType_GenericAlloc,		/* tp_alloc */
! 	times_new,			/* tp_new */
 	PyObject_GC_Del,		/* tp_free */
 };
--- 1121,1125 ----
 	0,				/* tp_init */
 	PyType_GenericAlloc,		/* tp_alloc */
! 	chain_new,			/* tp_new */
 	PyObject_GC_Del,		/* tp_free */
 };
***************
*** 1545,1548 ****
--- 1719,1723 ----
 	PyObject_HEAD
 	PyObject *element;
+ 	long cnt;
 } repeatobject;
 
***************
*** 1554,1559 ****
 	repeatobject *ro;
 	PyObject *element;
 
! 	if (!PyArg_UnpackTuple(args, "repeat", 1, 1, &element))
 		return NULL;
 
--- 1729,1735 ----
 	repeatobject *ro;
 	PyObject *element;
+ 	long cnt = -1;
 
! 	if (!PyArg_ParseTuple(args, "O|l:repeat", &element, &cnt))
 		return NULL;
 
***************
*** 1563,1566 ****
--- 1739,1743 ----
 	Py_INCREF(element);
 	ro->element = element;
+ 	ro->cnt = cnt;
 	return (PyObject *)ro;
 }
***************
*** 1585,1588 ****
--- 1762,1769 ----
 repeat_next(repeatobject *ro)
 {
+ 	if (ro->cnt == 0)
+ 		return NULL;
+ 	if (ro->cnt > 0)
+ 		ro->cnt--;
 	Py_INCREF(ro->element);
 	return ro->element;
***************
*** 1597,1601 ****
 
 PyDoc_STRVAR(repeat_doc,
! "repeat(element) -> create an iterator which returns the element endlessly.");
 
 PyTypeObject repeat_type = {
--- 1778,1784 ----
 
 PyDoc_STRVAR(repeat_doc,
! "repeat(element [,times]) -> create an iterator which returns the element\n\
! for the specified number of times. If not specified, returns the element\n\
! endlessly.");
 
 PyTypeObject repeat_type = {
***************
*** 1652,1656 ****
 Infinite iterators:\n\
 count([n]) --> n, n+1, n+2, ...\n\
! repeat(elem) --> elem, elem, elem, ...\n\
 \n\
 Iterators terminating on the shortest input sequence:\n\
--- 1835,1840 ----
 Infinite iterators:\n\
 count([n]) --> n, n+1, n+2, ...\n\
! cycle(p) --> p0, p1, ... plast, p0, p1, ...\n\
! repeat(elem [,n]) --> elem, elem, elem, ... endlessly or upto n times\n\
 \n\
 Iterators terminating on the shortest input sequence:\n\
***************
*** 1662,1666 ****
 imap(fun, p, q, ...) --> fun(p0, q0), fun(p1, q1), ...\n\
 starmap(fun, seq) --> fun(*seq[0]), fun(*seq[1]), ...\n\
! times(n, [obj]) --> obj, obj, ... for n times. obj defaults to None\n\
 takewhile(pred, seq) --> seq[0], seq[1], until pred fails\n\
 dropwhile(pred, seq) --> seq[n], seq[n+1], starting when pred fails\n\
--- 1846,1850 ----
 imap(fun, p, q, ...) --> fun(p0, q0), fun(p1, q1), ...\n\
 starmap(fun, seq) --> fun(*seq[0]), fun(*seq[1]), ...\n\
! chain(p, q, ...) --> p0, p1, ... plast, q0, q1, ... \n\
 takewhile(pred, seq) --> seq[0], seq[1], until pred fails\n\
 dropwhile(pred, seq) --> seq[n], seq[n+1], starting when pred fails\n\
***************
*** 1675,1678 ****
--- 1859,1863 ----
 	char *name;
 	PyTypeObject *typelist[] = {
+ 		&cycle_type,
 		&dropwhile_type,
 		&takewhile_type,
***************
*** 1680,1684 ****
 		&starmap_type,
 		&imap_type,
! 		&times_type,
 		&ifilter_type,
 		&ifilterfalse_type,
--- 1865,1869 ----
 		&starmap_type,
 		&imap_type,
! 		&chain_type,
 		&ifilter_type,
 		&ifilterfalse_type,
***************
*** 1695,1700 ****
 			return;
 		name = strchr(typelist[i]->tp_name, '.') + 1;
! 		if (name == NULL)
! 			return;
 		Py_INCREF(typelist[i]);
 		PyModule_AddObject(m, name, (PyObject *)typelist[i]);
--- 1880,1884 ----
 			return;
 		name = strchr(typelist[i]->tp_name, '.') + 1;
! 		assert (name != NULL);
 		Py_INCREF(typelist[i]);
 		PyModule_AddObject(m, name, (PyObject *)typelist[i]);

AltStyle によって変換されたページ (->オリジナル) /