C Code:
* Removed the ifilter flag wart by splitting it into two simpler functions. * Fixed comment tabbing in C code. * Factored module start-up code into a loop. Documentation: * Re-wrote introduction. * Addede examples for quantifiers. * Simplified python equivalent for islice(). * Documented split of ifilter(). Sets.py: * Replace old ifilter() usage with new.
This commit is contained in:
parent
cb3319f61e
commit
60eca9331a
|
@ -12,45 +12,43 @@ This module implements a number of iterator building blocks inspired
|
|||
by constructs from the Haskell and SML programming languages. Each
|
||||
has been recast in a form suitable for Python.
|
||||
|
||||
With the advent of iterators and generators in Python 2.3, each of
|
||||
these tools can be expressed easily and succinctly in pure python.
|
||||
Rather duplicating what can already be done, this module emphasizes
|
||||
providing value in other ways:
|
||||
The module standardizes a core set of fast, memory efficient tools
|
||||
that are useful by themselves or in combination. Standardization helps
|
||||
avoid the readability and reliability problems which arise when many
|
||||
different individuals create their own slightly varying implementations,
|
||||
each with their own quirks and naming conventions.
|
||||
|
||||
\begin{itemize}
|
||||
The tools are designed to combine readily with each another. This makes
|
||||
it easy to construct more specialized tools succinctly and efficiently
|
||||
in pure Python.
|
||||
|
||||
\item Instead of constructing an over-specialized toolset, this module
|
||||
provides basic building blocks that can be readily combined.
|
||||
For instance, SML provides a tabulation tool: \code{tabulate(\var{f})}
|
||||
which produces a sequence \code{f(0), f(1), ...}. This toolbox
|
||||
provides \function{imap()} and \function{count()} which can be combined
|
||||
to form \code{imap(\var{f}, count())} and produce an equivalent result.
|
||||
|
||||
For instance, SML provides a tabulation tool: \code{tabulate(\var{f})}
|
||||
which produces a sequence \code{f(0), f(1), ...}. This toolbox
|
||||
takes a different approach of providing \function{imap()} and
|
||||
\function{count()} which can be combined to form
|
||||
\code{imap(\var{f}, count())} and produce an equivalent result.
|
||||
Whether cast in pure python form or C code, tools that use iterators
|
||||
are more memory efficient (and faster) than their list based counterparts.
|
||||
Adopting the principles of just-in-time manufacturing, they create
|
||||
data when and where needed instead of consuming memory with the
|
||||
computer equivalent of ``inventory''.
|
||||
|
||||
\item Some tools were dropped because they offer no advantage over their
|
||||
pure python counterparts or because their behavior was too
|
||||
surprising.
|
||||
Some tools were omitted from the module because they offered no
|
||||
advantage over their pure python counterparts or because their behavior
|
||||
was too surprising.
|
||||
|
||||
For instance, SML provides a tool: \code{cycle(\var{seq})} which
|
||||
loops over the sequence elements and then starts again when the
|
||||
sequence is exhausted. The surprising behavior is the need for
|
||||
significant auxiliary storage (unusual for iterators). Also, it
|
||||
is trivially implemented in python with almost no performance
|
||||
penalty.
|
||||
For instance, SML provides a tool: \code{cycle(\var{seq})} which
|
||||
loops over the sequence elements and then starts again when the
|
||||
sequence is exhausted. The surprising behavior is the need for
|
||||
significant auxiliary storage (which is unusual for an iterator).
|
||||
If needed, the tool is readily constructible using pure Python.
|
||||
|
||||
\item Another source of value comes from standardizing a core set of tools
|
||||
to avoid the readability and reliability problems that arise when many
|
||||
different individuals create their own slightly varying implementations
|
||||
each with their own quirks and naming conventions.
|
||||
|
||||
\item Whether cast in pure python form or C code, tools that use iterators
|
||||
are more memory efficient (and faster) than their list based counterparts.
|
||||
Adopting the principles of just-in-time manufacturing, they create
|
||||
data when and where needed instead of consuming memory with the
|
||||
computer equivalent of ``inventory''.
|
||||
|
||||
\end{itemize}
|
||||
Other tools are being considered for inclusion in future versions of the
|
||||
module. For instance, the function
|
||||
\function{chain(\var{it0}, \var{it1}, ...})} would return elements from
|
||||
the first iterator until it was exhausted and then move on to each
|
||||
successive iterator. The module author welcomes suggestions for other
|
||||
basic building blocks.
|
||||
|
||||
\begin{seealso}
|
||||
\seetext{The Standard ML Basis Library,
|
||||
|
@ -107,24 +105,36 @@ by functions or loops that truncate the stream.
|
|||
\end{verbatim}
|
||||
\end{funcdesc}
|
||||
|
||||
\begin{funcdesc}{ifilter}{predicate, iterable \optional{, invert}}
|
||||
\begin{funcdesc}{ifilter}{predicate, iterable}
|
||||
Make an iterator that filters elements from iterable returning only
|
||||
those for which the predicate is \code{True}. If
|
||||
\var{invert} is \code{True}, then reverse the process and pass through
|
||||
only those elements for which the predicate is \code{False}.
|
||||
If \var{predicate} is \code{None}, return the items that are true
|
||||
(or false if \var{invert} has been set). Equivalent to:
|
||||
those for which the predicate is \code{True}.
|
||||
If \var{predicate} is \code{None}, return the items that are true.
|
||||
Equivalent to:
|
||||
|
||||
\begin{verbatim}
|
||||
def ifilter(predicate, iterable, invert=False):
|
||||
iterable = iter(iterable)
|
||||
while True:
|
||||
x = iterable.next()
|
||||
if predicate is None:
|
||||
b = bool(x)
|
||||
else:
|
||||
b = bool(predicate(x))
|
||||
if not invert and b or invert and not b:
|
||||
def ifilter(predicate, iterable):
|
||||
if predicate is None:
|
||||
def predicate(x):
|
||||
return x
|
||||
for x in iterable:
|
||||
if predicate(x):
|
||||
yield x
|
||||
\end{verbatim}
|
||||
\end{funcdesc}
|
||||
|
||||
\begin{funcdesc}{ifilterfalse}{predicate, iterable}
|
||||
Make an iterator that filters elements from iterable returning only
|
||||
those for which the predicate is \code{False}.
|
||||
If \var{predicate} is \code{None}, return the items that are false.
|
||||
Equivalent to:
|
||||
|
||||
\begin{verbatim}
|
||||
def ifilterfalse(predicate, iterable):
|
||||
if predicate is None:
|
||||
def predicate(x):
|
||||
return x
|
||||
for x in iterable:
|
||||
if not predicate(x):
|
||||
yield x
|
||||
\end{verbatim}
|
||||
\end{funcdesc}
|
||||
|
@ -169,21 +179,17 @@ by functions or loops that truncate the stream.
|
|||
|
||||
\begin{verbatim}
|
||||
def islice(iterable, *args):
|
||||
iterable = iter(iterable)
|
||||
s = slice(*args)
|
||||
next = s.start or 0
|
||||
stop = s.stop
|
||||
step = s.step or 1
|
||||
cnt = 0
|
||||
while True:
|
||||
while cnt < next:
|
||||
dummy = iterable.next()
|
||||
cnt += 1
|
||||
if cnt >= stop:
|
||||
break
|
||||
yield iterable.next()
|
||||
cnt += 1
|
||||
next += step
|
||||
for cnt, element in enumerate(iterable):
|
||||
if cnt < next:
|
||||
continue
|
||||
if cnt >= stop:
|
||||
break
|
||||
yield element
|
||||
next += step
|
||||
\end{verbatim}
|
||||
\end{funcdesc}
|
||||
|
||||
|
@ -324,6 +330,18 @@ from building blocks.
|
|||
|
||||
>>> def nth(iterable, n):
|
||||
... "Returns the nth item"
|
||||
... return islice(iterable, n, n+1).next()
|
||||
... return list(islice(iterable, n, n+1))
|
||||
|
||||
>>> def all(pred, seq):
|
||||
... "Returns True if pred(x) is True for every element in the iterable"
|
||||
... return not nth(ifilterfalse(pred, seq), 0)
|
||||
|
||||
>>> def some(pred, seq):
|
||||
... "Returns True if pred(x) is True at least one element in the iterable"
|
||||
... return bool(nth(ifilter(pred, seq), 0))
|
||||
|
||||
>>> def no(pred, seq):
|
||||
... "Returns True if pred(x) is False for every element in the iterable"
|
||||
... return not nth(ifilter(pred, seq), 0)
|
||||
|
||||
\end{verbatim}
|
||||
|
|
12
Lib/sets.py
12
Lib/sets.py
|
@ -57,7 +57,7 @@ what's tested is actually `z in y'.
|
|||
|
||||
|
||||
__all__ = ['BaseSet', 'Set', 'ImmutableSet']
|
||||
from itertools import ifilter
|
||||
from itertools import ifilter, ifilterfalse
|
||||
|
||||
class BaseSet(object):
|
||||
"""Common base class for mutable and immutable sets."""
|
||||
|
@ -204,9 +204,9 @@ class BaseSet(object):
|
|||
value = True
|
||||
selfdata = self._data
|
||||
otherdata = other._data
|
||||
for elt in ifilter(otherdata.has_key, selfdata, True):
|
||||
for elt in ifilterfalse(otherdata.has_key, selfdata):
|
||||
data[elt] = value
|
||||
for elt in ifilter(selfdata.has_key, otherdata, True):
|
||||
for elt in ifilterfalse(selfdata.has_key, otherdata):
|
||||
data[elt] = value
|
||||
return result
|
||||
|
||||
|
@ -227,7 +227,7 @@ class BaseSet(object):
|
|||
result = self.__class__()
|
||||
data = result._data
|
||||
value = True
|
||||
for elt in ifilter(other._data.has_key, self, True):
|
||||
for elt in ifilterfalse(other._data.has_key, self):
|
||||
data[elt] = value
|
||||
return result
|
||||
|
||||
|
@ -260,7 +260,7 @@ class BaseSet(object):
|
|||
self._binary_sanity_check(other)
|
||||
if len(self) > len(other): # Fast check for obvious cases
|
||||
return False
|
||||
for elt in ifilter(other._data.has_key, self, True):
|
||||
for elt in ifilterfalse(other._data.has_key, self):
|
||||
return False
|
||||
return True
|
||||
|
||||
|
@ -269,7 +269,7 @@ class BaseSet(object):
|
|||
self._binary_sanity_check(other)
|
||||
if len(self) < len(other): # Fast check for obvious cases
|
||||
return False
|
||||
for elt in ifilter(self._data.has_key, other, True):
|
||||
for elt in ifilterfalse(self._data.has_key, other):
|
||||
return False
|
||||
return True
|
||||
|
||||
|
|
|
@ -13,12 +13,19 @@ class TestBasicOps(unittest.TestCase):
|
|||
def isEven(x):
|
||||
return x%2==0
|
||||
self.assertEqual(list(ifilter(isEven, range(6))), [0,2,4])
|
||||
self.assertEqual(list(ifilter(isEven, range(6), True)), [1,3,5])
|
||||
self.assertEqual(list(ifilter(None, [0,1,0,2,0])), [1,2])
|
||||
self.assertRaises(TypeError, ifilter)
|
||||
self.assertRaises(TypeError, ifilter, 3)
|
||||
self.assertRaises(TypeError, ifilter, isEven, 3)
|
||||
self.assertRaises(TypeError, ifilter, isEven, [3], True, 4)
|
||||
|
||||
def test_ifilterfalse(self):
|
||||
def isEven(x):
|
||||
return x%2==0
|
||||
self.assertEqual(list(ifilterfalse(isEven, range(6))), [1,3,5])
|
||||
self.assertEqual(list(ifilterfalse(None, [0,1,0,2,0])), [0,0,0])
|
||||
self.assertRaises(TypeError, ifilterfalse)
|
||||
self.assertRaises(TypeError, ifilterfalse, 3)
|
||||
self.assertRaises(TypeError, ifilterfalse, isEven, 3)
|
||||
|
||||
def test_izip(self):
|
||||
ans = [(x,y) for x, y in izip('abc',count())]
|
||||
|
@ -133,7 +140,19 @@ Samuele
|
|||
|
||||
>>> def nth(iterable, n):
|
||||
... "Returns the nth item"
|
||||
... return islice(iterable, n, n+1).next()
|
||||
... return list(islice(iterable, n, n+1))
|
||||
|
||||
>>> def all(pred, seq):
|
||||
... "Returns True if pred(x) is True for every element in the iterable"
|
||||
... return not nth(ifilterfalse(pred, seq), 0)
|
||||
|
||||
>>> def some(pred, seq):
|
||||
... "Returns True if pred(x) is True at least one element in the iterable"
|
||||
... return bool(nth(ifilter(pred, seq), 0))
|
||||
|
||||
>>> def no(pred, seq):
|
||||
... "Returns True if pred(x) is False for every element in the iterable"
|
||||
... return not nth(ifilter(pred, seq), 0)
|
||||
|
||||
"""
|
||||
|
||||
|
|
|
@ -118,11 +118,11 @@ Afterwards, return every element until the iterable is exhausted.");
|
|||
PyTypeObject dropwhile_type = {
|
||||
PyObject_HEAD_INIT(NULL)
|
||||
0, /* ob_size */
|
||||
"itertools.dropwhile", /* tp_name */
|
||||
sizeof(dropwhileobject), /* tp_basicsize */
|
||||
"itertools.dropwhile", /* tp_name */
|
||||
sizeof(dropwhileobject), /* tp_basicsize */
|
||||
0, /* tp_itemsize */
|
||||
/* methods */
|
||||
(destructor)dropwhile_dealloc, /* tp_dealloc */
|
||||
(destructor)dropwhile_dealloc, /* tp_dealloc */
|
||||
0, /* tp_print */
|
||||
0, /* tp_getattr */
|
||||
0, /* tp_setattr */
|
||||
|
@ -139,13 +139,13 @@ PyTypeObject dropwhile_type = {
|
|||
0, /* tp_as_buffer */
|
||||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
|
||||
Py_TPFLAGS_BASETYPE, /* tp_flags */
|
||||
dropwhile_doc, /* tp_doc */
|
||||
dropwhile_doc, /* tp_doc */
|
||||
(traverseproc)dropwhile_traverse, /* tp_traverse */
|
||||
0, /* tp_clear */
|
||||
0, /* tp_richcompare */
|
||||
0, /* tp_weaklistoffset */
|
||||
(getiterfunc)dropwhile_getiter, /* tp_iter */
|
||||
(iternextfunc)dropwhile_next, /* tp_iternext */
|
||||
(getiterfunc)dropwhile_getiter, /* tp_iter */
|
||||
(iternextfunc)dropwhile_next, /* tp_iternext */
|
||||
0, /* tp_methods */
|
||||
0, /* tp_members */
|
||||
0, /* tp_getset */
|
||||
|
@ -156,7 +156,7 @@ PyTypeObject dropwhile_type = {
|
|||
0, /* tp_dictoffset */
|
||||
0, /* tp_init */
|
||||
PyType_GenericAlloc, /* tp_alloc */
|
||||
dropwhile_new, /* tp_new */
|
||||
dropwhile_new, /* tp_new */
|
||||
PyObject_GC_Del, /* tp_free */
|
||||
};
|
||||
|
||||
|
@ -271,11 +271,11 @@ predicate evaluates to true for each entry.");
|
|||
PyTypeObject takewhile_type = {
|
||||
PyObject_HEAD_INIT(NULL)
|
||||
0, /* ob_size */
|
||||
"itertools.takewhile", /* tp_name */
|
||||
sizeof(takewhileobject), /* tp_basicsize */
|
||||
"itertools.takewhile", /* tp_name */
|
||||
sizeof(takewhileobject), /* tp_basicsize */
|
||||
0, /* tp_itemsize */
|
||||
/* methods */
|
||||
(destructor)takewhile_dealloc, /* tp_dealloc */
|
||||
(destructor)takewhile_dealloc, /* tp_dealloc */
|
||||
0, /* tp_print */
|
||||
0, /* tp_getattr */
|
||||
0, /* tp_setattr */
|
||||
|
@ -292,13 +292,13 @@ PyTypeObject takewhile_type = {
|
|||
0, /* tp_as_buffer */
|
||||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
|
||||
Py_TPFLAGS_BASETYPE, /* tp_flags */
|
||||
takewhile_doc, /* tp_doc */
|
||||
takewhile_doc, /* tp_doc */
|
||||
(traverseproc)takewhile_traverse, /* tp_traverse */
|
||||
0, /* tp_clear */
|
||||
0, /* tp_richcompare */
|
||||
0, /* tp_weaklistoffset */
|
||||
(getiterfunc)takewhile_getiter, /* tp_iter */
|
||||
(iternextfunc)takewhile_next, /* tp_iternext */
|
||||
(getiterfunc)takewhile_getiter, /* tp_iter */
|
||||
(iternextfunc)takewhile_next, /* tp_iternext */
|
||||
0, /* tp_methods */
|
||||
0, /* tp_members */
|
||||
0, /* tp_getset */
|
||||
|
@ -309,7 +309,7 @@ PyTypeObject takewhile_type = {
|
|||
0, /* tp_dictoffset */
|
||||
0, /* tp_init */
|
||||
PyType_GenericAlloc, /* tp_alloc */
|
||||
takewhile_new, /* tp_new */
|
||||
takewhile_new, /* tp_new */
|
||||
PyObject_GC_Del, /* tp_free */
|
||||
};
|
||||
|
||||
|
@ -449,7 +449,7 @@ PyTypeObject islice_type = {
|
|||
sizeof(isliceobject), /* tp_basicsize */
|
||||
0, /* tp_itemsize */
|
||||
/* methods */
|
||||
(destructor)islice_dealloc, /* tp_dealloc */
|
||||
(destructor)islice_dealloc, /* tp_dealloc */
|
||||
0, /* tp_print */
|
||||
0, /* tp_getattr */
|
||||
0, /* tp_setattr */
|
||||
|
@ -466,13 +466,13 @@ PyTypeObject islice_type = {
|
|||
0, /* tp_as_buffer */
|
||||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
|
||||
Py_TPFLAGS_BASETYPE, /* tp_flags */
|
||||
islice_doc, /* tp_doc */
|
||||
(traverseproc)islice_traverse, /* tp_traverse */
|
||||
islice_doc, /* tp_doc */
|
||||
(traverseproc)islice_traverse, /* tp_traverse */
|
||||
0, /* tp_clear */
|
||||
0, /* tp_richcompare */
|
||||
0, /* tp_weaklistoffset */
|
||||
(getiterfunc)islice_getiter, /* tp_iter */
|
||||
(iternextfunc)islice_next, /* tp_iternext */
|
||||
(getiterfunc)islice_getiter, /* tp_iter */
|
||||
(iternextfunc)islice_next, /* tp_iternext */
|
||||
0, /* tp_methods */
|
||||
0, /* tp_members */
|
||||
0, /* tp_getset */
|
||||
|
@ -589,11 +589,11 @@ with a argument tuple taken from the given sequence.");
|
|||
PyTypeObject starmap_type = {
|
||||
PyObject_HEAD_INIT(NULL)
|
||||
0, /* ob_size */
|
||||
"itertools.starmap", /* tp_name */
|
||||
sizeof(starmapobject), /* tp_basicsize */
|
||||
"itertools.starmap", /* tp_name */
|
||||
sizeof(starmapobject), /* tp_basicsize */
|
||||
0, /* tp_itemsize */
|
||||
/* methods */
|
||||
(destructor)starmap_dealloc, /* tp_dealloc */
|
||||
(destructor)starmap_dealloc, /* tp_dealloc */
|
||||
0, /* tp_print */
|
||||
0, /* tp_getattr */
|
||||
0, /* tp_setattr */
|
||||
|
@ -610,13 +610,13 @@ PyTypeObject starmap_type = {
|
|||
0, /* tp_as_buffer */
|
||||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
|
||||
Py_TPFLAGS_BASETYPE, /* tp_flags */
|
||||
starmap_doc, /* tp_doc */
|
||||
(traverseproc)starmap_traverse, /* tp_traverse */
|
||||
starmap_doc, /* tp_doc */
|
||||
(traverseproc)starmap_traverse, /* tp_traverse */
|
||||
0, /* tp_clear */
|
||||
0, /* tp_richcompare */
|
||||
0, /* tp_weaklistoffset */
|
||||
(getiterfunc)starmap_getiter, /* tp_iter */
|
||||
(iternextfunc)starmap_next, /* tp_iternext */
|
||||
(getiterfunc)starmap_getiter, /* tp_iter */
|
||||
(iternextfunc)starmap_next, /* tp_iternext */
|
||||
0, /* tp_methods */
|
||||
0, /* tp_members */
|
||||
0, /* tp_getset */
|
||||
|
@ -627,7 +627,7 @@ PyTypeObject starmap_type = {
|
|||
0, /* tp_dictoffset */
|
||||
0, /* tp_init */
|
||||
PyType_GenericAlloc, /* tp_alloc */
|
||||
starmap_new, /* tp_new */
|
||||
starmap_new, /* tp_new */
|
||||
PyObject_GC_Del, /* tp_free */
|
||||
};
|
||||
|
||||
|
@ -783,8 +783,8 @@ iterables.");
|
|||
PyTypeObject imap_type = {
|
||||
PyObject_HEAD_INIT(NULL)
|
||||
0, /* ob_size */
|
||||
"itertools.imap", /* tp_name */
|
||||
sizeof(imapobject), /* tp_basicsize */
|
||||
"itertools.imap", /* tp_name */
|
||||
sizeof(imapobject), /* tp_basicsize */
|
||||
0, /* tp_itemsize */
|
||||
/* methods */
|
||||
(destructor)imap_dealloc, /* tp_dealloc */
|
||||
|
@ -821,7 +821,7 @@ PyTypeObject imap_type = {
|
|||
0, /* tp_dictoffset */
|
||||
0, /* tp_init */
|
||||
PyType_GenericAlloc, /* tp_alloc */
|
||||
imap_new, /* tp_new */
|
||||
imap_new, /* tp_new */
|
||||
PyObject_GC_Del, /* tp_free */
|
||||
};
|
||||
|
||||
|
@ -908,8 +908,8 @@ instances of obj (default is None).");
|
|||
PyTypeObject times_type = {
|
||||
PyObject_HEAD_INIT(NULL)
|
||||
0, /* ob_size */
|
||||
"itertools.times", /* tp_name */
|
||||
sizeof(timesobject), /* tp_basicsize */
|
||||
"itertools.times", /* tp_name */
|
||||
sizeof(timesobject), /* tp_basicsize */
|
||||
0, /* tp_itemsize */
|
||||
/* methods */
|
||||
(destructor)times_dealloc, /* tp_dealloc */
|
||||
|
@ -929,13 +929,13 @@ PyTypeObject times_type = {
|
|||
0, /* tp_as_buffer */
|
||||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
|
||||
Py_TPFLAGS_BASETYPE, /* tp_flags */
|
||||
times_doc, /* tp_doc */
|
||||
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 */
|
||||
(getiterfunc)times_getiter, /* tp_iter */
|
||||
(iternextfunc)times_next, /* tp_iternext */
|
||||
0, /* tp_methods */
|
||||
0, /* tp_members */
|
||||
0, /* tp_getset */
|
||||
|
@ -957,7 +957,6 @@ typedef struct {
|
|||
PyObject_HEAD
|
||||
PyObject *func;
|
||||
PyObject *it;
|
||||
long invert;
|
||||
} ifilterobject;
|
||||
|
||||
PyTypeObject ifilter_type;
|
||||
|
@ -965,17 +964,13 @@ PyTypeObject ifilter_type;
|
|||
static PyObject *
|
||||
ifilter_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
PyObject *func, *seq, *invert=NULL;
|
||||
PyObject *func, *seq;
|
||||
PyObject *it;
|
||||
ifilterobject *lz;
|
||||
long inv=0;
|
||||
|
||||
if (!PyArg_UnpackTuple(args, "ifilter", 2, 3, &func, &seq, &invert))
|
||||
if (!PyArg_UnpackTuple(args, "ifilter", 2, 2, &func, &seq))
|
||||
return NULL;
|
||||
|
||||
if (invert != NULL && PyObject_IsTrue(invert))
|
||||
inv = 1;
|
||||
|
||||
/* Get iterator. */
|
||||
it = PyObject_GetIter(seq);
|
||||
if (it == NULL)
|
||||
|
@ -990,7 +985,6 @@ ifilter_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
|||
Py_INCREF(func);
|
||||
lz->func = func;
|
||||
lz->it = it;
|
||||
lz->invert = inv;
|
||||
|
||||
return (PyObject *)lz;
|
||||
}
|
||||
|
@ -1046,7 +1040,7 @@ ifilter_next(ifilterobject *lz)
|
|||
ok = PyObject_IsTrue(good);
|
||||
Py_DECREF(good);
|
||||
}
|
||||
if (ok ^ lz->invert)
|
||||
if (ok)
|
||||
return item;
|
||||
Py_DECREF(item);
|
||||
}
|
||||
|
@ -1060,20 +1054,19 @@ ifilter_getiter(PyObject *lz)
|
|||
}
|
||||
|
||||
PyDoc_STRVAR(ifilter_doc,
|
||||
"ifilter(function or None, sequence [, invert]) --> ifilter object\n\
|
||||
"ifilter(function or None, sequence) --> ifilter object\n\
|
||||
\n\
|
||||
Return those items of sequence for which function(item) is true. If\n\
|
||||
invert is set to True, return items for which function(item) if False.\n\
|
||||
If function is None, return the items that are true (unless invert is set).");
|
||||
Return those items of sequence for which function(item) is true.\n\
|
||||
If function is None, return the items that are true.");
|
||||
|
||||
PyTypeObject ifilter_type = {
|
||||
PyObject_HEAD_INIT(NULL)
|
||||
0, /* ob_size */
|
||||
"itertools.ifilter", /* tp_name */
|
||||
sizeof(ifilterobject), /* tp_basicsize */
|
||||
"itertools.ifilter", /* tp_name */
|
||||
sizeof(ifilterobject), /* tp_basicsize */
|
||||
0, /* tp_itemsize */
|
||||
/* methods */
|
||||
(destructor)ifilter_dealloc, /* tp_dealloc */
|
||||
(destructor)ifilter_dealloc, /* tp_dealloc */
|
||||
0, /* tp_print */
|
||||
0, /* tp_getattr */
|
||||
0, /* tp_setattr */
|
||||
|
@ -1090,13 +1083,13 @@ PyTypeObject ifilter_type = {
|
|||
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 */
|
||||
ifilter_doc, /* tp_doc */
|
||||
(traverseproc)ifilter_traverse, /* tp_traverse */
|
||||
0, /* tp_clear */
|
||||
0, /* tp_richcompare */
|
||||
0, /* tp_weaklistoffset */
|
||||
(getiterfunc)ifilter_getiter, /* tp_iter */
|
||||
(iternextfunc)ifilter_next, /* tp_iternext */
|
||||
(getiterfunc)ifilter_getiter, /* tp_iter */
|
||||
(iternextfunc)ifilter_next, /* tp_iternext */
|
||||
0, /* tp_methods */
|
||||
0, /* tp_members */
|
||||
0, /* tp_getset */
|
||||
|
@ -1107,7 +1100,161 @@ PyTypeObject ifilter_type = {
|
|||
0, /* tp_dictoffset */
|
||||
0, /* tp_init */
|
||||
PyType_GenericAlloc, /* tp_alloc */
|
||||
ifilter_new, /* tp_new */
|
||||
ifilter_new, /* tp_new */
|
||||
PyObject_GC_Del, /* tp_free */
|
||||
};
|
||||
|
||||
|
||||
/* ifilterfalse object ************************************************************/
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
PyObject *func;
|
||||
PyObject *it;
|
||||
} ifilterfalseobject;
|
||||
|
||||
PyTypeObject ifilterfalse_type;
|
||||
|
||||
static PyObject *
|
||||
ifilterfalse_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
PyObject *func, *seq, *invert=NULL;
|
||||
PyObject *it;
|
||||
ifilterfalseobject *lz;
|
||||
|
||||
if (!PyArg_UnpackTuple(args, "ifilterfalse", 2, 2, &func, &seq))
|
||||
return NULL;
|
||||
|
||||
/* Get iterator. */
|
||||
it = PyObject_GetIter(seq);
|
||||
if (it == NULL)
|
||||
return NULL;
|
||||
|
||||
/* create ifilterfalseobject structure */
|
||||
lz = (ifilterfalseobject *)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
|
||||
ifilterfalse_dealloc(ifilterfalseobject *lz)
|
||||
{
|
||||
PyObject_GC_UnTrack(lz);
|
||||
Py_XDECREF(lz->func);
|
||||
Py_XDECREF(lz->it);
|
||||
lz->ob_type->tp_free(lz);
|
||||
}
|
||||
|
||||
static int
|
||||
ifilterfalse_traverse(ifilterfalseobject *lz, visitproc visit, void *arg)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (lz->it) {
|
||||
err = visit(lz->it, arg);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
if (lz->func) {
|
||||
err = visit(lz->func, arg);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
ifilterfalse_next(ifilterfalseobject *lz)
|
||||
{
|
||||
PyObject *item;
|
||||
long ok;
|
||||
|
||||
for (;;) {
|
||||
item = PyIter_Next(lz->it);
|
||||
if (item == NULL)
|
||||
return NULL;
|
||||
|
||||
if (lz->func == Py_None) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
ifilterfalse_getiter(PyObject *lz)
|
||||
{
|
||||
Py_INCREF(lz);
|
||||
return lz;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(ifilterfalse_doc,
|
||||
"ifilterfalse(function or None, sequence) --> ifilterfalse object\n\
|
||||
\n\
|
||||
Return those items of sequence for which function(item) is false.\n\
|
||||
If function is None, return the items that are false.");
|
||||
|
||||
PyTypeObject ifilterfalse_type = {
|
||||
PyObject_HEAD_INIT(NULL)
|
||||
0, /* ob_size */
|
||||
"itertools.ifilterfalse", /* tp_name */
|
||||
sizeof(ifilterfalseobject), /* tp_basicsize */
|
||||
0, /* tp_itemsize */
|
||||
/* methods */
|
||||
(destructor)ifilterfalse_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 */
|
||||
ifilterfalse_doc, /* tp_doc */
|
||||
(traverseproc)ifilterfalse_traverse, /* tp_traverse */
|
||||
0, /* tp_clear */
|
||||
0, /* tp_richcompare */
|
||||
0, /* tp_weaklistoffset */
|
||||
(getiterfunc)ifilterfalse_getiter, /* tp_iter */
|
||||
(iternextfunc)ifilterfalse_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 */
|
||||
ifilterfalse_new, /* tp_new */
|
||||
PyObject_GC_Del, /* tp_free */
|
||||
};
|
||||
|
||||
|
@ -1161,8 +1308,8 @@ integers starting from zero or, if specified, from firstval.");
|
|||
PyTypeObject count_type = {
|
||||
PyObject_HEAD_INIT(NULL)
|
||||
0, /* ob_size */
|
||||
"itertools.count", /* tp_name */
|
||||
sizeof(countobject), /* tp_basicsize */
|
||||
"itertools.count", /* tp_name */
|
||||
sizeof(countobject), /* tp_basicsize */
|
||||
0, /* tp_itemsize */
|
||||
/* methods */
|
||||
(destructor)PyObject_Del, /* tp_dealloc */
|
||||
|
@ -1181,13 +1328,13 @@ PyTypeObject count_type = {
|
|||
0, /* tp_setattro */
|
||||
0, /* tp_as_buffer */
|
||||
Py_TPFLAGS_DEFAULT, /* tp_flags */
|
||||
count_doc, /* tp_doc */
|
||||
count_doc, /* tp_doc */
|
||||
0, /* tp_traverse */
|
||||
0, /* tp_clear */
|
||||
0, /* tp_richcompare */
|
||||
0, /* tp_weaklistoffset */
|
||||
(getiterfunc)count_getiter, /* tp_iter */
|
||||
(iternextfunc)count_next, /* tp_iternext */
|
||||
(getiterfunc)count_getiter, /* tp_iter */
|
||||
(iternextfunc)count_next, /* tp_iternext */
|
||||
0, /* tp_methods */
|
||||
0, /* tp_members */
|
||||
0, /* tp_getset */
|
||||
|
@ -1349,11 +1496,11 @@ a list.");
|
|||
PyTypeObject izip_type = {
|
||||
PyObject_HEAD_INIT(NULL)
|
||||
0, /* ob_size */
|
||||
"itertools.izip", /* tp_name */
|
||||
sizeof(izipobject), /* tp_basicsize */
|
||||
"itertools.izip", /* tp_name */
|
||||
sizeof(izipobject), /* tp_basicsize */
|
||||
0, /* tp_itemsize */
|
||||
/* methods */
|
||||
(destructor)izip_dealloc, /* tp_dealloc */
|
||||
(destructor)izip_dealloc, /* tp_dealloc */
|
||||
0, /* tp_print */
|
||||
0, /* tp_getattr */
|
||||
0, /* tp_setattr */
|
||||
|
@ -1370,13 +1517,13 @@ PyTypeObject izip_type = {
|
|||
0, /* tp_as_buffer */
|
||||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
|
||||
Py_TPFLAGS_BASETYPE, /* tp_flags */
|
||||
izip_doc, /* tp_doc */
|
||||
izip_doc, /* tp_doc */
|
||||
(traverseproc)izip_traverse, /* tp_traverse */
|
||||
0, /* tp_clear */
|
||||
0, /* tp_richcompare */
|
||||
0, /* tp_weaklistoffset */
|
||||
(getiterfunc)izip_getiter, /* tp_iter */
|
||||
(iternextfunc)izip_next, /* tp_iternext */
|
||||
(getiterfunc)izip_getiter, /* tp_iter */
|
||||
(iternextfunc)izip_next, /* tp_iternext */
|
||||
0, /* tp_methods */
|
||||
0, /* tp_members */
|
||||
0, /* tp_getset */
|
||||
|
@ -1387,7 +1534,7 @@ PyTypeObject izip_type = {
|
|||
0, /* tp_dictoffset */
|
||||
0, /* tp_init */
|
||||
PyType_GenericAlloc, /* tp_alloc */
|
||||
izip_new, /* tp_new */
|
||||
izip_new, /* tp_new */
|
||||
PyObject_GC_Del, /* tp_free */
|
||||
};
|
||||
|
||||
|
@ -1458,7 +1605,7 @@ PyTypeObject repeat_type = {
|
|||
sizeof(repeatobject), /* tp_basicsize */
|
||||
0, /* tp_itemsize */
|
||||
/* methods */
|
||||
(destructor)repeat_dealloc, /* tp_dealloc */
|
||||
(destructor)repeat_dealloc, /* tp_dealloc */
|
||||
0, /* tp_print */
|
||||
0, /* tp_getattr */
|
||||
0, /* tp_setattr */
|
||||
|
@ -1475,13 +1622,13 @@ PyTypeObject repeat_type = {
|
|||
0, /* tp_as_buffer */
|
||||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
|
||||
Py_TPFLAGS_BASETYPE, /* tp_flags */
|
||||
repeat_doc, /* tp_doc */
|
||||
(traverseproc)repeat_traverse, /* tp_traverse */
|
||||
repeat_doc, /* tp_doc */
|
||||
(traverseproc)repeat_traverse, /* tp_traverse */
|
||||
0, /* tp_clear */
|
||||
0, /* tp_richcompare */
|
||||
0, /* tp_weaklistoffset */
|
||||
(getiterfunc)repeat_getiter, /* tp_iter */
|
||||
(iternextfunc)repeat_next, /* tp_iternext */
|
||||
(getiterfunc)repeat_getiter, /* tp_iter */
|
||||
(iternextfunc)repeat_next, /* tp_iternext */
|
||||
0, /* tp_methods */
|
||||
0, /* tp_members */
|
||||
0, /* tp_getset */
|
||||
|
@ -1508,8 +1655,8 @@ repeat(elem) --> elem, elem, elem, ...\n\
|
|||
\n\
|
||||
Iterators terminating on the shortest input sequence:\n\
|
||||
izip(p, q, ...) --> (p[0], q[0]), (p[1], q[1]), ... \n\
|
||||
ifilter(pred, seq, invert=False) --> elements of seq where\n\
|
||||
pred(elem) is True (or False if invert is set)\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\
|
||||
imap(fun, p, q, ...) --> fun(p0, q0), fun(p1, q1), ...\n\
|
||||
|
@ -1523,56 +1670,33 @@ dropwhile(pred, seq) --> seq[n], seq[n+1], starting when pred fails\n\
|
|||
PyMODINIT_FUNC
|
||||
inititertools(void)
|
||||
{
|
||||
int i;
|
||||
PyObject *m;
|
||||
char *name;
|
||||
PyTypeObject *typelist[] = {
|
||||
&dropwhile_type,
|
||||
&takewhile_type,
|
||||
&islice_type,
|
||||
&starmap_type,
|
||||
&imap_type,
|
||||
×_type,
|
||||
&ifilter_type,
|
||||
&ifilterfalse_type,
|
||||
&count_type,
|
||||
&izip_type,
|
||||
&repeat_type,
|
||||
NULL
|
||||
};
|
||||
|
||||
m = Py_InitModule3("itertools", NULL, module_doc);
|
||||
|
||||
PyModule_AddObject(m, "dropwhile", (PyObject *)&dropwhile_type);
|
||||
if (PyType_Ready(&dropwhile_type) < 0)
|
||||
return;
|
||||
Py_INCREF(&dropwhile_type);
|
||||
|
||||
PyModule_AddObject(m, "takewhile", (PyObject *)&takewhile_type);
|
||||
if (PyType_Ready(&takewhile_type) < 0)
|
||||
return;
|
||||
Py_INCREF(&takewhile_type);
|
||||
|
||||
PyModule_AddObject(m, "islice", (PyObject *)&islice_type);
|
||||
if (PyType_Ready(&islice_type) < 0)
|
||||
return;
|
||||
Py_INCREF(&islice_type);
|
||||
|
||||
PyModule_AddObject(m, "starmap", (PyObject *)&starmap_type);
|
||||
if (PyType_Ready(&starmap_type) < 0)
|
||||
return;
|
||||
Py_INCREF(&starmap_type);
|
||||
|
||||
PyModule_AddObject(m, "imap", (PyObject *)&imap_type);
|
||||
if (PyType_Ready(&imap_type) < 0)
|
||||
return;
|
||||
Py_INCREF(&imap_type);
|
||||
|
||||
PyModule_AddObject(m, "times", (PyObject *)×_type);
|
||||
if (PyType_Ready(×_type) < 0)
|
||||
return;
|
||||
Py_INCREF(×_type);
|
||||
|
||||
if (PyType_Ready(&ifilter_type) < 0)
|
||||
return;
|
||||
Py_INCREF(&ifilter_type);
|
||||
PyModule_AddObject(m, "ifilter", (PyObject *)&ifilter_type);
|
||||
|
||||
if (PyType_Ready(&count_type) < 0)
|
||||
return;
|
||||
Py_INCREF(&count_type);
|
||||
PyModule_AddObject(m, "count", (PyObject *)&count_type);
|
||||
|
||||
if (PyType_Ready(&izip_type) < 0)
|
||||
return;
|
||||
Py_INCREF(&izip_type);
|
||||
PyModule_AddObject(m, "izip", (PyObject *)&izip_type);
|
||||
|
||||
if (PyType_Ready(&repeat_type) < 0)
|
||||
return;
|
||||
Py_INCREF(&repeat_type);
|
||||
PyModule_AddObject(m, "repeat", (PyObject *)&repeat_type);
|
||||
for (i=0 ; typelist[i] != NULL ; i++) {
|
||||
if (PyType_Ready(typelist[i]) < 0)
|
||||
return;
|
||||
name = strchr(typelist[i]->tp_name, '.') + 1;
|
||||
if (name == NULL)
|
||||
return;
|
||||
Py_INCREF(typelist[i]);
|
||||
PyModule_AddObject(m, name, (PyObject *)typelist[i]);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue