From 17301e9fab311badbbe26a1efcb2decf637b324a Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Thu, 13 Mar 2008 00:19:26 +0000 Subject: Issue 2186 and 2187. Move filter from itertools to builtins. --- Doc/library/itertools.rst | 19 +----- Lib/filecmp.py | 4 +- Lib/test/test_itertools.py | 1 + Modules/itertoolsmodule.c | 145 ------------------------------------------- Python/bltinmodule.c | 149 ++++++++++++++++++++++++++++++++++++++++----- 5 files changed, 138 insertions(+), 180 deletions(-) diff --git a/Doc/library/itertools.rst b/Doc/library/itertools.rst index 0d74c59..368e40d 100644 --- a/Doc/library/itertools.rst +++ b/Doc/library/itertools.rst @@ -234,21 +234,6 @@ loops that truncate the stream. self.currkey = self.keyfunc(self.currvalue) -.. function:: ifilter(predicate, iterable) - - Make an iterator that filters elements from iterable returning only those for - which the predicate is ``True``. If *predicate* is ``None``, return the items - that are true. This function is the same as the built-in :func:`filter` - function. Equivalent to:: - - def ifilter(predicate, iterable): - if predicate is None: - predicate = bool - for x in iterable: - if predicate(x): - yield x - - .. function:: ifilterfalse(predicate, iterable) Make an iterator that filters elements from iterable returning only those for @@ -606,13 +591,13 @@ which incur interpreter overhead. :: def any(seq, pred=None): "Returns True if pred(x) is true for at least one element in the iterable" - for elem in ifilter(pred, seq): + for elem in filter(pred, seq): return True return False def no(seq, pred=None): "Returns True if pred(x) is false for every element in the iterable" - for elem in ifilter(pred, seq): + for elem in filter(pred, seq): return False return True diff --git a/Lib/filecmp.py b/Lib/filecmp.py index 12ba3ef..14e1eb4 100644 --- a/Lib/filecmp.py +++ b/Lib/filecmp.py @@ -12,7 +12,7 @@ Functions: import os import stat import warnings -from itertools import ifilter, ifilterfalse, imap, izip +from itertools import ifilterfalse, imap, izip __all__ = ["cmp","dircmp","cmpfiles"] @@ -132,7 +132,7 @@ class dircmp: def phase1(self): # Compute common names a = dict(izip(imap(os.path.normcase, self.left_list), self.left_list)) b = dict(izip(imap(os.path.normcase, self.right_list), self.right_list)) - self.common = list(map(a.__getitem__, ifilter(b.__contains__, a))) + self.common = list(map(a.__getitem__, filter(b.__contains__, a))) self.left_only = list(map(a.__getitem__, ifilterfalse(b.__contains__, a))) self.right_only = list(map(b.__getitem__, ifilterfalse(a.__contains__, b))) diff --git a/Lib/test/test_itertools.py b/Lib/test/test_itertools.py index 4e0902b..13dc1f9 100644 --- a/Lib/test/test_itertools.py +++ b/Lib/test/test_itertools.py @@ -8,6 +8,7 @@ import random from functools import reduce maxsize = test_support.MAX_Py_ssize_t minsize = -maxsize-1 +ifilter = filter def lzip(*args): return list(zip(*args)) diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c index c0de36d..1f2a43b 100644 --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -2208,149 +2208,6 @@ static PyTypeObject combinations_type = { }; -/* ifilter object ************************************************************/ - -typedef struct { - PyObject_HEAD - PyObject *func; - PyObject *it; -} ifilterobject; - -static PyTypeObject ifilter_type; - -static PyObject * -ifilter_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - PyObject *func, *seq; - PyObject *it; - ifilterobject *lz; - - if (type == &ifilter_type && !_PyArg_NoKeywords("ifilter()", kwds)) - return NULL; - - if (!PyArg_UnpackTuple(args, "ifilter", 2, 2, &func, &seq)) - return NULL; - - /* Get iterator. */ - it = PyObject_GetIter(seq); - if (it == NULL) - return NULL; - - /* create ifilterobject structure */ - lz = (ifilterobject *)type->tp_alloc(type, 0); - if (lz == NULL) { - Py_DECREF(it); - return NULL; - } - Py_INCREF(func); - lz->func = func; - lz->it = it; - - return (PyObject *)lz; -} - -static void -ifilter_dealloc(ifilterobject *lz) -{ - PyObject_GC_UnTrack(lz); - Py_XDECREF(lz->func); - Py_XDECREF(lz->it); - Py_TYPE(lz)->tp_free(lz); -} - -static int -ifilter_traverse(ifilterobject *lz, visitproc visit, void *arg) -{ - Py_VISIT(lz->it); - Py_VISIT(lz->func); - return 0; -} - -static PyObject * -ifilter_next(ifilterobject *lz) -{ - PyObject *item; - PyObject *it = lz->it; - long ok; - PyObject *(*iternext)(PyObject *); - - assert(PyIter_Check(it)); - iternext = *Py_TYPE(it)->tp_iternext; - for (;;) { - item = iternext(it); - if (item == NULL) - return NULL; - - if (lz->func == Py_None || lz->func == (PyObject *)&PyBool_Type) { - ok = PyObject_IsTrue(item); - } else { - PyObject *good; - good = PyObject_CallFunctionObjArgs(lz->func, - item, NULL); - if (good == NULL) { - Py_DECREF(item); - return NULL; - } - ok = PyObject_IsTrue(good); - Py_DECREF(good); - } - if (ok) - return item; - Py_DECREF(item); - } -} - -PyDoc_STRVAR(ifilter_doc, -"ifilter(function or None, sequence) --> ifilter object\n\ -\n\ -Return those items of sequence for which function(item) is true.\n\ -If function is None, return the items that are true."); - -static PyTypeObject ifilter_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "itertools.ifilter", /* tp_name */ - sizeof(ifilterobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)ifilter_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 */ - ifilter_doc, /* tp_doc */ - (traverseproc)ifilter_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - PyObject_SelfIter, /* tp_iter */ - (iternextfunc)ifilter_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 */ - 0, /* tp_alloc */ - ifilter_new, /* tp_new */ - PyObject_GC_Del, /* tp_free */ -}; - - /* ifilterfalse object ************************************************************/ typedef struct { @@ -3208,7 +3065,6 @@ repeat(elem [,n]) --> elem, elem, elem, ... endlessly or up to n times\n\ Iterators terminating on the shortest input sequence:\n\ izip(p, q, ...) --> (p[0], q[0]), (p[1], q[1]), ... \n\ izip_longest(p, q, ...) --> (p[0], q[0]), (p[1], q[1]), ... \n\ -ifilter(pred, seq) --> elements of seq where pred(elem) is True\n\ ifilterfalse(pred, seq) --> elements of seq where pred(elem) is False\n\ islice(seq, [start,] stop [, step]) --> elements from\n\ seq[start:stop:step]\n\ @@ -3242,7 +3098,6 @@ inititertools(void) &starmap_type, &imap_type, &chain_type, - &ifilter_type, &ifilterfalse_type, &count_type, &izip_type, diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 70237bf..7baaf14 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -277,29 +277,146 @@ PyDoc_STRVAR(bin_doc, Return the binary representation of an integer or long integer."); +typedef struct { + PyObject_HEAD + PyObject *func; + PyObject *it; +} filterobject; + +PyTypeObject PyFilter_Type; + static PyObject * -builtin_filter(PyObject *self, PyObject *args) +filter_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { - PyObject *itertools, *ifilter, *result; - itertools = PyImport_ImportModuleNoBlock("itertools"); - if (itertools == NULL) + PyObject *func, *seq; + PyObject *it; + filterobject *lz; + + if (type == &PyFilter_Type && !_PyArg_NoKeywords("filter()", kwds)) return NULL; - ifilter = PyObject_GetAttrString(itertools, "ifilter"); - Py_DECREF(itertools); - if (ifilter == NULL) + + if (!PyArg_UnpackTuple(args, "filter", 2, 2, &func, &seq)) return NULL; - result = PyObject_Call(ifilter, args, NULL); - Py_DECREF(ifilter); - return result; + + /* Get iterator. */ + it = PyObject_GetIter(seq); + if (it == NULL) + return NULL; + + /* create filterobject structure */ + lz = (filterobject *)type->tp_alloc(type, 0); + if (lz == NULL) { + Py_DECREF(it); + return NULL; + } + Py_INCREF(func); + lz->func = func; + lz->it = it; + + return (PyObject *)lz; +} + +static void +filter_dealloc(filterobject *lz) +{ + PyObject_GC_UnTrack(lz); + Py_XDECREF(lz->func); + Py_XDECREF(lz->it); + Py_TYPE(lz)->tp_free(lz); +} + +static int +filter_traverse(filterobject *lz, visitproc visit, void *arg) +{ + Py_VISIT(lz->it); + Py_VISIT(lz->func); + return 0; +} + +static PyObject * +filter_next(filterobject *lz) +{ + PyObject *item; + PyObject *it = lz->it; + long ok; + PyObject *(*iternext)(PyObject *); + + assert(PyIter_Check(it)); + iternext = *Py_TYPE(it)->tp_iternext; + for (;;) { + item = iternext(it); + if (item == NULL) + return NULL; + + if (lz->func == Py_None || lz->func == (PyObject *)&PyBool_Type) { + ok = PyObject_IsTrue(item); + } else { + PyObject *good; + good = PyObject_CallFunctionObjArgs(lz->func, + item, NULL); + if (good == NULL) { + Py_DECREF(item); + return NULL; + } + ok = PyObject_IsTrue(good); + Py_DECREF(good); + } + if (ok) + return item; + Py_DECREF(item); + } } PyDoc_STRVAR(filter_doc, -"filter(predicate, iterable) -> iterator\n\ +"filter(function or None, sequence) --> filter object\n\ \n\ -Return an iterator yielding only those elements of the input iterable\n\ -for which the predicate (a Boolean function) returns true.\n\ -If the predicate is None, 'lambda x: bool(x)' is assumed.\n\ -(This is identical to itertools.ifilter().)"); +Return an iterator yielding those items of sequence for which function(item)\n\ +is true. If function is None, return the items that are true."); + +PyTypeObject PyFilter_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "filter", /* tp_name */ + sizeof(filterobject), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + (destructor)filter_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 */ + filter_doc, /* tp_doc */ + (traverseproc)filter_traverse, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + PyObject_SelfIter, /* tp_iter */ + (iternextfunc)filter_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 */ + filter_new, /* tp_new */ + PyObject_GC_Del, /* tp_free */ +}; + static PyObject * builtin_format(PyObject *self, PyObject *args) @@ -1763,7 +1880,6 @@ static PyMethodDef builtin_methods[] = { {"divmod", builtin_divmod, METH_VARARGS, divmod_doc}, {"eval", builtin_eval, METH_VARARGS, eval_doc}, {"exec", builtin_exec, METH_VARARGS, exec_doc}, - {"filter", builtin_filter, METH_VARARGS, filter_doc}, {"format", builtin_format, METH_VARARGS, format_doc}, {"getattr", builtin_getattr, METH_VARARGS, getattr_doc}, {"globals", (PyCFunction)builtin_globals, METH_NOARGS, globals_doc}, @@ -1843,6 +1959,7 @@ _PyBuiltin_Init(void) #endif SETBUILTIN("dict", &PyDict_Type); SETBUILTIN("enumerate", &PyEnum_Type); + SETBUILTIN("filter", &PyFilter_Type); SETBUILTIN("float", &PyFloat_Type); SETBUILTIN("frozenset", &PyFrozenSet_Type); SETBUILTIN("property", &PyProperty_Type); -- cgit v0.12