]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Issues 2186 and 2187. Move map() from itertools to builtins.
authorRaymond Hettinger <python@rcn.com>
Thu, 13 Mar 2008 01:26:19 +0000 (01:26 +0000)
committerRaymond Hettinger <python@rcn.com>
Thu, 13 Mar 2008 01:26:19 +0000 (01:26 +0000)
Doc/library/itertools.rst
Lib/filecmp.py
Lib/test/seq_tests.py
Lib/test/test_heapq.py
Lib/test/test_itertools.py
Lib/test/test_set.py
Modules/itertoolsmodule.c
Python/bltinmodule.c

index 368e40d77c865d2ed1c861d22479ef2d002b4c5e..032c0b8e8a1184bc9a7002183a5def0f1f6b0040 100644 (file)
@@ -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))
index 14e1eb4b8514f38442b2653a6e6be93b2f5e658a..00fc13518ea3cf8bde5202d5e529cb1573a83831 100644 (file)
@@ -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)))
index a3815e216e841054f85c8f99411c91ec61cdea07..dfa18c5558a3302485edfc71a4659c962db86878 100644 (file)
@@ -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
index 8ae1637aa9bc5a14bcf6aecbae6c70ccef9cb2e7..7969d6ec899892a5f1c6dc21c560d52b950cde94 100644 (file)
@@ -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
index 13dc1f98f9734debc18c7c2e50cb37adfe1bbba5..7d905d81e07c975d4d94bf8e8dbdc39a7b7c72e1 100644 (file)
@@ -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))
index 9e3d64ff23a48f649d3fd8d089e61c40aa720538..ca3c02e383ed3b9fc4ac8533396c3d09f1d8486a 100644 (file)
@@ -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):
 
index 1f2a43bc5dfd3ab4c1b2258857188df4e3bd5b5f..f1d33cd9751092675490dcadbd6ce8a1f2b28ecb 100644 (file)
@@ -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,
index 7baaf14213c8d1b653f909a32dda962d69f894e9..024729e18a9fe63a0a923e6d78be1563a0c6f174 100644 (file)
@@ -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);