summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRaymond Hettinger <python@rcn.com>2008-03-13 01:26:19 (GMT)
committerRaymond Hettinger <python@rcn.com>2008-03-13 01:26:19 (GMT)
commita6c6037f882573c9965e4fac74765357e42148e4 (patch)
treeb35d3490d3d547e3bd86f11e3ad761b2c6445f6b
parent17301e9fab311badbbe26a1efcb2decf637b324a (diff)
downloadcpython-a6c6037f882573c9965e4fac74765357e42148e4.zip
cpython-a6c6037f882573c9965e4fac74765357e42148e4.tar.gz
cpython-a6c6037f882573c9965e4fac74765357e42148e4.tar.bz2
Issues 2186 and 2187. Move map() from itertools to builtins.
-rw-r--r--Doc/library/itertools.rst37
-rw-r--r--Lib/filecmp.py6
-rw-r--r--Lib/test/seq_tests.py4
-rw-r--r--Lib/test/test_heapq.py4
-rw-r--r--Lib/test/test_itertools.py1
-rw-r--r--Lib/test/test_set.py4
-rw-r--r--Modules/itertoolsmodule.c151
-rw-r--r--Python/bltinmodule.c154
8 files changed, 158 insertions, 203 deletions
diff --git a/Doc/library/itertools.rst b/Doc/library/itertools.rst
index 368e40d..032c0b8 100644
--- a/Doc/library/itertools.rst
+++ b/Doc/library/itertools.rst
@@ -22,9 +22,8 @@ The tools are designed to combine readily with one another. This makes it easy
to construct more specialized tools succinctly and efficiently in pure Python.
For instance, SML provides a tabulation tool: ``tabulate(f)`` which produces a
-sequence ``f(0), f(1), ...``. This toolbox provides :func:`imap` and
-:func:`count` which can be combined to form ``imap(f, count())`` and produce an
-equivalent result.
+sequence ``f(0), f(1), ...``. But, this effect can be achieved in Python
+by combining :func:`map` and :func:`count` to form ``map(f, count())``.
Likewise, the functional tools are designed to work well with the high-speed
functions provided by the :mod:`operator` module.
@@ -138,7 +137,7 @@ loops that truncate the stream.
.. function:: count([n])
Make an iterator that returns consecutive integers starting with *n*. If not
- specified *n* defaults to zero. Often used as an argument to :func:`imap` to
+ specified *n* defaults to zero. Often used as an argument to :func:`map` to
generate consecutive data points. Also, used with :func:`izip` to add sequence
numbers. Equivalent to::
@@ -248,22 +247,6 @@ loops that truncate the stream.
yield x
-.. function:: imap(function, *iterables)
-
- Make an iterator that computes the function using arguments from each of the
- iterables. This function is the same as the built-in :func:`map` function.
- Equivalent to::
-
- def imap(function, *iterables):
- iterables = [iter(it) for it in iterables)
- while True:
- args = [next(it) for it in iterables]
- if function is None:
- yield tuple(args)
- else:
- yield function(*args)
-
-
.. function:: islice(iterable, [start,] stop [, step])
Make an iterator that returns selected elements from the iterable. If *start* is
@@ -421,7 +404,7 @@ loops that truncate the stream.
.. function:: repeat(object[, times])
Make an iterator that returns *object* over and over again. Runs indefinitely
- unless the *times* argument is specified. Used as argument to :func:`imap` for
+ unless the *times* argument is specified. Used as argument to :func:`map` for
invariant parameters to the called function. Also used with :func:`izip` to
create an invariant part of a tuple record. Equivalent to::
@@ -437,9 +420,9 @@ loops that truncate the stream.
.. function:: starmap(function, iterable)
Make an iterator that computes the function using arguments obtained from
- the iterable. Used instead of :func:`imap` when argument parameters are already
+ the iterable. Used instead of :func:`map` when argument parameters are already
grouped in tuples from a single iterable (the data has been "pre-zipped"). The
- difference between :func:`imap` and :func:`starmap` parallels the distinction
+ difference between :func:`map` and :func:`starmap` parallels the distinction
between ``function(a,b)`` and ``function(*c)``. Equivalent to::
def starmap(function, iterable):
@@ -507,7 +490,7 @@ can be combined. ::
Check 1202 is for $823.14
>>> import operator
- >>> for cube in imap(operator.pow, range(1,5), repeat(3)):
+ >>> for cube in map(operator.pow, range(1,5), repeat(3)):
... print(cube)
...
1
@@ -577,7 +560,7 @@ which incur interpreter overhead. ::
def tabulate(function):
"Return function(0), function(1), ..."
- return imap(function, count())
+ return map(function, count())
def nth(iterable, n):
"Returns the nth item or raise StopIteration"
@@ -603,7 +586,7 @@ which incur interpreter overhead. ::
def quantify(seq, pred=None):
"Count how many times the predicate is true in the sequence"
- return sum(imap(pred, seq))
+ return sum(map(pred, seq))
def padnone(seq):
"""Returns the sequence elements and then returns None indefinitely.
@@ -617,7 +600,7 @@ which incur interpreter overhead. ::
return chain.from_iterable(repeat(seq, n))
def dotproduct(vec1, vec2):
- return sum(imap(operator.mul, vec1, vec2))
+ return sum(map(operator.mul, vec1, vec2))
def flatten(listOfLists):
return list(chain.from_iterable(listOfLists))
diff --git a/Lib/filecmp.py b/Lib/filecmp.py
index 14e1eb4..00fc135 100644
--- a/Lib/filecmp.py
+++ b/Lib/filecmp.py
@@ -12,7 +12,7 @@ Functions:
import os
import stat
import warnings
-from itertools import ifilterfalse, imap, izip
+from itertools import ifilterfalse, izip
__all__ = ["cmp","dircmp","cmpfiles"]
@@ -130,8 +130,8 @@ class dircmp:
self.right_list.sort()
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))
+ a = dict(izip(map(os.path.normcase, self.left_list), self.left_list))
+ b = dict(izip(map(os.path.normcase, self.right_list), self.right_list))
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/seq_tests.py b/Lib/test/seq_tests.py
index a3815e2..dfa18c5 100644
--- a/Lib/test/seq_tests.py
+++ b/Lib/test/seq_tests.py
@@ -79,10 +79,10 @@ class IterFuncStop:
def __next__(self):
raise StopIteration
-from itertools import chain, imap
+from itertools import chain, map
def itermulti(seqn):
'Test multiple tiers of iterators'
- return chain(imap(lambda x:x, iterfunc(IterGen(Sequence(seqn)))))
+ return chain(map(lambda x:x, iterfunc(IterGen(Sequence(seqn)))))
class CommonTest(unittest.TestCase):
# The type to be tested
diff --git a/Lib/test/test_heapq.py b/Lib/test/test_heapq.py
index 8ae1637..7969d6e 100644
--- a/Lib/test/test_heapq.py
+++ b/Lib/test/test_heapq.py
@@ -260,10 +260,10 @@ class S:
def __next__(self):
raise StopIteration
-from itertools import chain, imap
+from itertools import chain, map
def L(seqn):
'Test multiple tiers of iterators'
- return chain(imap(lambda x:x, R(Ig(G(seqn)))))
+ return chain(map(lambda x:x, R(Ig(G(seqn)))))
class TestErrorHandling(unittest.TestCase):
# only for C implementation
diff --git a/Lib/test/test_itertools.py b/Lib/test/test_itertools.py
index 13dc1f9..7d905d8 100644
--- a/Lib/test/test_itertools.py
+++ b/Lib/test/test_itertools.py
@@ -9,6 +9,7 @@ from functools import reduce
maxsize = test_support.MAX_Py_ssize_t
minsize = -maxsize-1
ifilter = filter
+imap = map
def lzip(*args):
return list(zip(*args))
diff --git a/Lib/test/test_set.py b/Lib/test/test_set.py
index 9e3d64f..ca3c02e 100644
--- a/Lib/test/test_set.py
+++ b/Lib/test/test_set.py
@@ -1560,10 +1560,10 @@ class S:
def __next__(self):
raise StopIteration
-from itertools import chain, imap
+from itertools import chain
def L(seqn):
'Test multiple tiers of iterators'
- return chain(imap(lambda x:x, R(Ig(G(seqn)))))
+ return chain(map(lambda x:x, R(Ig(G(seqn)))))
class TestVariousIteratorArgs(unittest.TestCase):
diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c
index 1f2a43b..f1d33cd 100644
--- a/Modules/itertoolsmodule.c
+++ b/Modules/itertoolsmodule.c
@@ -1418,155 +1418,6 @@ static PyTypeObject starmap_type = {
};
-/* imap object ************************************************************/
-
-typedef struct {
- PyObject_HEAD
- PyObject *iters;
- PyObject *func;
-} imapobject;
-
-static PyTypeObject imap_type;
-
-static PyObject *
-imap_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
- PyObject *it, *iters, *func;
- imapobject *lz;
- Py_ssize_t numargs, i;
-
- if (type == &imap_type && !_PyArg_NoKeywords("imap()", kwds))
- return NULL;
-
- numargs = PyTuple_Size(args);
- if (numargs < 2) {
- PyErr_SetString(PyExc_TypeError,
- "imap() must have at least two arguments.");
- return NULL;
- }
-
- iters = PyTuple_New(numargs-1);
- if (iters == NULL)
- return NULL;
-
- for (i=1 ; i<numargs ; i++) {
- /* Get iterator. */
- it = PyObject_GetIter(PyTuple_GET_ITEM(args, i));
- if (it == NULL) {
- Py_DECREF(iters);
- return NULL;
- }
- PyTuple_SET_ITEM(iters, i-1, it);
- }
-
- /* create imapobject structure */
- lz = (imapobject *)type->tp_alloc(type, 0);
- if (lz == NULL) {
- Py_DECREF(iters);
- return NULL;
- }
- lz->iters = iters;
- func = PyTuple_GET_ITEM(args, 0);
- Py_INCREF(func);
- lz->func = func;
-
- return (PyObject *)lz;
-}
-
-static void
-imap_dealloc(imapobject *lz)
-{
- PyObject_GC_UnTrack(lz);
- Py_XDECREF(lz->iters);
- Py_XDECREF(lz->func);
- Py_TYPE(lz)->tp_free(lz);
-}
-
-static int
-imap_traverse(imapobject *lz, visitproc visit, void *arg)
-{
- Py_VISIT(lz->iters);
- Py_VISIT(lz->func);
- return 0;
-}
-
-static PyObject *
-imap_next(imapobject *lz)
-{
- PyObject *val;
- PyObject *argtuple;
- PyObject *result;
- Py_ssize_t numargs, i;
-
- numargs = PyTuple_Size(lz->iters);
- argtuple = PyTuple_New(numargs);
- if (argtuple == NULL)
- return NULL;
-
- for (i=0 ; i<numargs ; i++) {
- val = PyIter_Next(PyTuple_GET_ITEM(lz->iters, i));
- if (val == NULL) {
- Py_DECREF(argtuple);
- return NULL;
- }
- PyTuple_SET_ITEM(argtuple, i, val);
- }
- result = PyObject_Call(lz->func, argtuple, NULL);
- Py_DECREF(argtuple);
- return result;
-}
-
-PyDoc_STRVAR(imap_doc,
-"imap(func, *iterables) --> imap object\n\
-\n\
-Make an iterator that computes the function using arguments from\n\
-each of the iterables. Stops when the shortest iterable is exhausted.");
-
-static PyTypeObject imap_type = {
- PyVarObject_HEAD_INIT(NULL, 0)
- "itertools.imap", /* tp_name */
- sizeof(imapobject), /* tp_basicsize */
- 0, /* tp_itemsize */
- /* methods */
- (destructor)imap_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 */
- imap_doc, /* tp_doc */
- (traverseproc)imap_traverse, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- PyObject_SelfIter, /* tp_iter */
- (iternextfunc)imap_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 */
- imap_new, /* tp_new */
- PyObject_GC_Del, /* tp_free */
-};
-
-
/* chain object ************************************************************/
typedef struct {
@@ -3068,7 +2919,6 @@ izip_longest(p, q, ...) --> (p[0], q[0]), (p[1], q[1]), ... \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\
starmap(fun, seq) --> fun(*seq[0]), fun(*seq[1]), ...\n\
tee(it, n=2) --> (it1, it2 , ... itn) splits one iterator into n\n\
chain(p, q, ...) --> p0, p1, ... plast, q0, q1, ... \n\
@@ -3096,7 +2946,6 @@ inititertools(void)
&takewhile_type,
&islice_type,
&starmap_type,
- &imap_type,
&chain_type,
&ifilterfalse_type,
&count_type,
diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c
index 7baaf14..024729e 100644
--- a/Python/bltinmodule.c
+++ b/Python/bltinmodule.c
@@ -864,31 +864,153 @@ Return the identity of an object. This is guaranteed to be unique among\n\
simultaneously existing objects. (Hint: it's the object's memory address.)");
+/* map object ************************************************************/
+
+typedef struct {
+ PyObject_HEAD
+ PyObject *iters;
+ PyObject *func;
+} mapobject;
+
+PyTypeObject PyMap_Type;
+
static PyObject *
-builtin_map(PyObject *self, PyObject *args)
+map_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
- PyObject *itertools, *imap, *result;
- itertools = PyImport_ImportModuleNoBlock("itertools");
- if (itertools == NULL)
+ PyObject *it, *iters, *func;
+ mapobject *lz;
+ Py_ssize_t numargs, i;
+
+ if (type == &PyMap_Type && !_PyArg_NoKeywords("map()", kwds))
return NULL;
- imap = PyObject_GetAttrString(itertools, "imap");
- Py_DECREF(itertools);
- if (imap == NULL)
+
+ numargs = PyTuple_Size(args);
+ if (numargs < 2) {
+ PyErr_SetString(PyExc_TypeError,
+ "map() must have at least two arguments.");
+ return NULL;
+ }
+
+ iters = PyTuple_New(numargs-1);
+ if (iters == NULL)
+ return NULL;
+
+ for (i=1 ; i<numargs ; i++) {
+ /* Get iterator. */
+ it = PyObject_GetIter(PyTuple_GET_ITEM(args, i));
+ if (it == NULL) {
+ Py_DECREF(iters);
+ return NULL;
+ }
+ PyTuple_SET_ITEM(iters, i-1, it);
+ }
+
+ /* create mapobject structure */
+ lz = (mapobject *)type->tp_alloc(type, 0);
+ if (lz == NULL) {
+ Py_DECREF(iters);
+ return NULL;
+ }
+ lz->iters = iters;
+ func = PyTuple_GET_ITEM(args, 0);
+ Py_INCREF(func);
+ lz->func = func;
+
+ return (PyObject *)lz;
+}
+
+static void
+map_dealloc(mapobject *lz)
+{
+ PyObject_GC_UnTrack(lz);
+ Py_XDECREF(lz->iters);
+ Py_XDECREF(lz->func);
+ Py_TYPE(lz)->tp_free(lz);
+}
+
+static int
+map_traverse(mapobject *lz, visitproc visit, void *arg)
+{
+ Py_VISIT(lz->iters);
+ Py_VISIT(lz->func);
+ return 0;
+}
+
+static PyObject *
+map_next(mapobject *lz)
+{
+ PyObject *val;
+ PyObject *argtuple;
+ PyObject *result;
+ Py_ssize_t numargs, i;
+
+ numargs = PyTuple_Size(lz->iters);
+ argtuple = PyTuple_New(numargs);
+ if (argtuple == NULL)
return NULL;
- result = PyObject_Call(imap, args, NULL);
- Py_DECREF(imap);
+
+ for (i=0 ; i<numargs ; i++) {
+ val = PyIter_Next(PyTuple_GET_ITEM(lz->iters, i));
+ if (val == NULL) {
+ Py_DECREF(argtuple);
+ return NULL;
+ }
+ PyTuple_SET_ITEM(argtuple, i, val);
+ }
+ result = PyObject_Call(lz->func, argtuple, NULL);
+ Py_DECREF(argtuple);
return result;
}
PyDoc_STRVAR(map_doc,
-"map(function, iterable[, iterable, ...]) -> iterator\n\
+"map(func, *iterables) --> map object\n\
\n\
-Return an iterator yielding the results of applying the function to the\n\
-items of the argument iterables(s). If more than one iterable is given,\n\
-the function is called with an argument list consisting of the\n\
-corresponding item of each iterable, until an iterable is exhausted.\n\
-(This is identical to itertools.imap().)");
+Make an iterator that computes the function using arguments from\n\
+each of the iterables. Stops when the shortest iterable is exhausted.");
+PyTypeObject PyMap_Type = {
+ PyVarObject_HEAD_INIT(&PyType_Type, 0)
+ "map", /* tp_name */
+ sizeof(mapobject), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ /* methods */
+ (destructor)map_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 */
+ map_doc, /* tp_doc */
+ (traverseproc)map_traverse, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ PyObject_SelfIter, /* tp_iter */
+ (iternextfunc)map_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 */
+ map_new, /* tp_new */
+ PyObject_GC_Del, /* tp_free */
+};
static PyObject *
builtin_next(PyObject *self, PyObject *args)
@@ -1893,7 +2015,6 @@ static PyMethodDef builtin_methods[] = {
{"iter", builtin_iter, METH_VARARGS, iter_doc},
{"len", builtin_len, METH_O, len_doc},
{"locals", (PyCFunction)builtin_locals, METH_NOARGS, locals_doc},
- {"map", builtin_map, METH_VARARGS, map_doc},
{"max", (PyCFunction)builtin_max, METH_VARARGS | METH_KEYWORDS, max_doc},
{"min", (PyCFunction)builtin_min, METH_VARARGS | METH_KEYWORDS, min_doc},
{"next", (PyCFunction)builtin_next, METH_VARARGS, next_doc},
@@ -1965,6 +2086,7 @@ _PyBuiltin_Init(void)
SETBUILTIN("property", &PyProperty_Type);
SETBUILTIN("int", &PyLong_Type);
SETBUILTIN("list", &PyList_Type);
+ SETBUILTIN("map", &PyMap_Type);
SETBUILTIN("object", &PyBaseObject_Type);
SETBUILTIN("range", &PyRange_Type);
SETBUILTIN("reversed", &PyReversed_Type);