[Python-3000-checkins] r61357 - in python/branches/py3k: 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

raymond.hettinger python-3000-checkins at python.org
Thu Mar 13 02:26:20 CET 2008


Author: raymond.hettinger
Date: Thu Mar 13 02:26:19 2008
New Revision: 61357

Modified:
   python/branches/py3k/Doc/library/itertools.rst
   python/branches/py3k/Lib/filecmp.py
   python/branches/py3k/Lib/test/seq_tests.py
   python/branches/py3k/Lib/test/test_heapq.py
   python/branches/py3k/Lib/test/test_itertools.py
   python/branches/py3k/Lib/test/test_set.py
   python/branches/py3k/Modules/itertoolsmodule.c
   python/branches/py3k/Python/bltinmodule.c
Log:
Issues 2186 and 2187. Move map() from itertools to builtins.

Modified: python/branches/py3k/Doc/library/itertools.rst
==============================================================================
--- python/branches/py3k/Doc/library/itertools.rst	(original)
+++ python/branches/py3k/Doc/library/itertools.rst	Thu Mar 13 02:26:19 2008
@@ -22,9 +22,8 @@
 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 @@
 .. 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 @@
                   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 @@
 .. 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 @@
 .. 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 @@
    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 @@
 
    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 @@
 
    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 @@
        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))

Modified: python/branches/py3k/Lib/filecmp.py
==============================================================================
--- python/branches/py3k/Lib/filecmp.py	(original)
+++ python/branches/py3k/Lib/filecmp.py	Thu Mar 13 02:26:19 2008
@@ -12,7 +12,7 @@
 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 @@
         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)))

Modified: python/branches/py3k/Lib/test/seq_tests.py
==============================================================================
--- python/branches/py3k/Lib/test/seq_tests.py	(original)
+++ python/branches/py3k/Lib/test/seq_tests.py	Thu Mar 13 02:26:19 2008
@@ -79,10 +79,10 @@
     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

Modified: python/branches/py3k/Lib/test/test_heapq.py
==============================================================================
--- python/branches/py3k/Lib/test/test_heapq.py	(original)
+++ python/branches/py3k/Lib/test/test_heapq.py	Thu Mar 13 02:26:19 2008
@@ -260,10 +260,10 @@
     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

Modified: python/branches/py3k/Lib/test/test_itertools.py
==============================================================================
--- python/branches/py3k/Lib/test/test_itertools.py	(original)
+++ python/branches/py3k/Lib/test/test_itertools.py	Thu Mar 13 02:26:19 2008
@@ -9,6 +9,7 @@
 maxsize = test_support.MAX_Py_ssize_t
 minsize = -maxsize-1
 ifilter = filter
+imap = map
 
 def lzip(*args):
     return list(zip(*args))

Modified: python/branches/py3k/Lib/test/test_set.py
==============================================================================
--- python/branches/py3k/Lib/test/test_set.py	(original)
+++ python/branches/py3k/Lib/test/test_set.py	Thu Mar 13 02:26:19 2008
@@ -1560,10 +1560,10 @@
     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):
 

Modified: python/branches/py3k/Modules/itertoolsmodule.c
==============================================================================
--- python/branches/py3k/Modules/itertoolsmodule.c	(original)
+++ python/branches/py3k/Modules/itertoolsmodule.c	Thu Mar 13 02:26:19 2008
@@ -1418,155 +1418,6 @@
 };
 
 
-/* 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 @@
 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 @@
 		&takewhile_type,
 		&islice_type,
 		&starmap_type,
-		&imap_type,
 		&chain_type,
 		&ifilterfalse_type,
 		&count_type,

Modified: python/branches/py3k/Python/bltinmodule.c
==============================================================================
--- python/branches/py3k/Python/bltinmodule.c	(original)
+++ python/branches/py3k/Python/bltinmodule.c	Thu Mar 13 02:26:19 2008
@@ -864,31 +864,153 @@
 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)
-		return NULL;
-	imap = PyObject_GetAttrString(itertools, "imap");
-	Py_DECREF(itertools);
-	if (imap == NULL)
+	PyObject *it, *iters, *func;
+	mapobject *lz;
+	Py_ssize_t numargs, i;
+
+	if (type == &PyMap_Type && !_PyArg_NoKeywords("map()", kwds))
+		return 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;
-	result = PyObject_Call(imap, args, NULL);
-	Py_DECREF(imap);
+
+	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;
+
+	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 @@
  	{"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 @@
 	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);


More information about the Python-3000-checkins mailing list