mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
Replace map(None, *iterables) with zip(*iterables).
This commit is contained in:
parent
86def6cb2b
commit
1dfde1ddc0
9 changed files with 20 additions and 90 deletions
|
@ -648,17 +648,7 @@ available. They are listed here in alphabetical order.
|
||||||
Return an iterator that applies *function* to every item of *iterable*,
|
Return an iterator that applies *function* to every item of *iterable*,
|
||||||
yielding the results. If additional *iterable* arguments are passed,
|
yielding the results. If additional *iterable* arguments are passed,
|
||||||
*function* must take that many arguments and is applied to the items from all
|
*function* must take that many arguments and is applied to the items from all
|
||||||
iterables in parallel. If one iterable is shorter than another it is assumed
|
iterables in parallel.
|
||||||
to be extended with ``None`` items. If *function* is ``None``, the identity
|
|
||||||
function is assumed; if there are multiple arguments, :func:`map` returns a
|
|
||||||
list consisting of tuples containing the corresponding items from all
|
|
||||||
iterables (a kind of transpose operation). The *iterable* arguments may be a
|
|
||||||
sequence or any iterable object; the result is always a list.
|
|
||||||
|
|
||||||
Note that for only one *iterable* argument, ``map(function, iterable)`` is
|
|
||||||
equivalent to the generator expression ``(function(item) for item in
|
|
||||||
iterable)`` if *function* is not ``None``.
|
|
||||||
|
|
||||||
|
|
||||||
.. function:: max(iterable[, args...], *[, key])
|
.. function:: max(iterable[, args...], *[, key])
|
||||||
|
|
||||||
|
|
|
@ -204,21 +204,13 @@ loops that truncate the stream.
|
||||||
.. function:: imap(function, *iterables)
|
.. function:: imap(function, *iterables)
|
||||||
|
|
||||||
Make an iterator that computes the function using arguments from each of the
|
Make an iterator that computes the function using arguments from each of the
|
||||||
iterables. If *function* is set to ``None``, then :func:`imap` returns the
|
iterables. Equivalent to::
|
||||||
arguments as a tuple. Like :func:`map` but stops when the shortest iterable is
|
|
||||||
exhausted instead of filling in ``None`` for shorter iterables. The reason for
|
|
||||||
the difference is that infinite iterator arguments are typically an error for
|
|
||||||
:func:`map` (because the output is fully evaluated) but represent a common and
|
|
||||||
useful way of supplying arguments to :func:`imap`. Equivalent to::
|
|
||||||
|
|
||||||
def imap(function, *iterables):
|
def imap(function, *iterables):
|
||||||
iterables = map(iter, iterables)
|
iterables = [iter(it) for it in iterables)
|
||||||
while True:
|
while True:
|
||||||
args = [next(i) for i in iterables]
|
args = [next(it) for it in iterables]
|
||||||
if function is None:
|
yield function(*args)
|
||||||
yield tuple(args)
|
|
||||||
else:
|
|
||||||
yield function(*args)
|
|
||||||
|
|
||||||
|
|
||||||
.. function:: islice(iterable, [start,] stop [, step])
|
.. function:: islice(iterable, [start,] stop [, step])
|
||||||
|
|
|
@ -351,7 +351,8 @@ def nsmallest(n, iterable, key=None):
|
||||||
Equivalent to: sorted(iterable, key=key)[:n]
|
Equivalent to: sorted(iterable, key=key)[:n]
|
||||||
"""
|
"""
|
||||||
in1, in2 = tee(iterable)
|
in1, in2 = tee(iterable)
|
||||||
it = izip(map(key, in1), count(), in2) # decorate
|
keys = in1 if key is None else map(key, in1)
|
||||||
|
it = izip(keys, count(), in2) # decorate
|
||||||
result = _nsmallest(n, it)
|
result = _nsmallest(n, it)
|
||||||
return list(map(itemgetter(2), result)) # undecorate
|
return list(map(itemgetter(2), result)) # undecorate
|
||||||
|
|
||||||
|
@ -362,7 +363,8 @@ def nlargest(n, iterable, key=None):
|
||||||
Equivalent to: sorted(iterable, key=key, reverse=True)[:n]
|
Equivalent to: sorted(iterable, key=key, reverse=True)[:n]
|
||||||
"""
|
"""
|
||||||
in1, in2 = tee(iterable)
|
in1, in2 = tee(iterable)
|
||||||
it = izip(map(key, in1), map(neg, count()), in2) # decorate
|
keys = in1 if key is None else map(key, in1)
|
||||||
|
it = izip(keys, map(neg, count()), in2) # decorate
|
||||||
result = _nlargest(n, it)
|
result = _nlargest(n, it)
|
||||||
return list(map(itemgetter(2), result)) # undecorate
|
return list(map(itemgetter(2), result)) # undecorate
|
||||||
|
|
||||||
|
|
|
@ -1099,18 +1099,6 @@ class BuiltinTest(unittest.TestCase):
|
||||||
# self.assertRaises(TypeError, long, Foo5())
|
# self.assertRaises(TypeError, long, Foo5())
|
||||||
|
|
||||||
def test_map(self):
|
def test_map(self):
|
||||||
self.assertEqual(
|
|
||||||
list(map(None, 'hello')),
|
|
||||||
[('h',), ('e',), ('l',), ('l',), ('o',)]
|
|
||||||
)
|
|
||||||
self.assertEqual(
|
|
||||||
list(map(None, 'abcd', 'efg')),
|
|
||||||
[('a', 'e'), ('b', 'f'), ('c', 'g')]
|
|
||||||
)
|
|
||||||
self.assertEqual(
|
|
||||||
list(map(None, range(3))),
|
|
||||||
[(0,), (1,), (2,)]
|
|
||||||
)
|
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
list(map(lambda x: x*x, range(1,4))),
|
list(map(lambda x: x*x, range(1,4))),
|
||||||
[1, 4, 9]
|
[1, 4, 9]
|
||||||
|
@ -1145,18 +1133,10 @@ class BuiltinTest(unittest.TestCase):
|
||||||
list(map(plus, [1, 3, 7], [4, 9, 2], [1, 1, 0])),
|
list(map(plus, [1, 3, 7], [4, 9, 2], [1, 1, 0])),
|
||||||
[1+4+1, 3+9+1, 7+2+0]
|
[1+4+1, 3+9+1, 7+2+0]
|
||||||
)
|
)
|
||||||
self.assertEqual(
|
|
||||||
list(map(None, Squares(10))),
|
|
||||||
[(0,), (1,), (4,), (9,), (16,), (25,), (36,), (49,), (64,), (81,)]
|
|
||||||
)
|
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
list(map(int, Squares(10))),
|
list(map(int, Squares(10))),
|
||||||
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
|
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
|
||||||
)
|
)
|
||||||
self.assertEqual(
|
|
||||||
list(map(None, Squares(3), Squares(2))),
|
|
||||||
[(0,0), (1,1)]
|
|
||||||
)
|
|
||||||
def Max(a, b):
|
def Max(a, b):
|
||||||
if a is None:
|
if a is None:
|
||||||
return b
|
return b
|
||||||
|
@ -1169,7 +1149,6 @@ class BuiltinTest(unittest.TestCase):
|
||||||
)
|
)
|
||||||
self.assertRaises(TypeError, map)
|
self.assertRaises(TypeError, map)
|
||||||
self.assertRaises(TypeError, map, lambda x: x, 42)
|
self.assertRaises(TypeError, map, lambda x: x, 42)
|
||||||
self.assertEqual(list(map(None, [42])), [(42,)])
|
|
||||||
class BadSeq:
|
class BadSeq:
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
raise ValueError
|
raise ValueError
|
||||||
|
|
|
@ -382,13 +382,10 @@ class TestCase(unittest.TestCase):
|
||||||
|
|
||||||
# Test map()'s use of iterators.
|
# Test map()'s use of iterators.
|
||||||
def test_builtin_map(self):
|
def test_builtin_map(self):
|
||||||
self.assertEqual(list(map(None, SequenceClass(5))),
|
|
||||||
[(0,), (1,), (2,), (3,), (4,)])
|
|
||||||
self.assertEqual(list(map(lambda x: x+1, SequenceClass(5))),
|
self.assertEqual(list(map(lambda x: x+1, SequenceClass(5))),
|
||||||
list(range(1, 6)))
|
list(range(1, 6)))
|
||||||
|
|
||||||
d = {"one": 1, "two": 2, "three": 3}
|
d = {"one": 1, "two": 2, "three": 3}
|
||||||
self.assertEqual(list(map(None, d)), [(k,) for k in d])
|
|
||||||
self.assertEqual(list(map(lambda k, d=d: (k, d[k]), d)),
|
self.assertEqual(list(map(lambda k, d=d: (k, d[k]), d)),
|
||||||
list(d.items()))
|
list(d.items()))
|
||||||
dkeys = list(d.keys())
|
dkeys = list(d.keys())
|
||||||
|
@ -396,11 +393,6 @@ class TestCase(unittest.TestCase):
|
||||||
i,
|
i,
|
||||||
i < len(d) and dkeys[i] or None)
|
i < len(d) and dkeys[i] or None)
|
||||||
for i in range(3)]
|
for i in range(3)]
|
||||||
self.assertEqual(list(map(None,
|
|
||||||
d,
|
|
||||||
SequenceClass(5),
|
|
||||||
iter(d.keys()))),
|
|
||||||
expected)
|
|
||||||
|
|
||||||
f = open(TESTFN, "w")
|
f = open(TESTFN, "w")
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -236,7 +236,7 @@ class TestBasicOps(unittest.TestCase):
|
||||||
self.assertEqual(list(izip_longest('abcdef')), list(zip('abcdef')))
|
self.assertEqual(list(izip_longest('abcdef')), list(zip('abcdef')))
|
||||||
|
|
||||||
self.assertEqual(list(izip_longest('abc', 'defg', **{})),
|
self.assertEqual(list(izip_longest('abc', 'defg', **{})),
|
||||||
list(map(None, list('abc')+[None], 'defg'))) # empty keyword dict
|
list(izip(list('abc')+[None], 'defg'))) # empty keyword dict
|
||||||
self.assertRaises(TypeError, izip_longest, 3)
|
self.assertRaises(TypeError, izip_longest, 3)
|
||||||
self.assertRaises(TypeError, izip_longest, range(3), 3)
|
self.assertRaises(TypeError, izip_longest, range(3), 3)
|
||||||
|
|
||||||
|
@ -281,14 +281,17 @@ class TestBasicOps(unittest.TestCase):
|
||||||
def test_imap(self):
|
def test_imap(self):
|
||||||
self.assertEqual(list(imap(operator.pow, range(3), range(1,7))),
|
self.assertEqual(list(imap(operator.pow, range(3), range(1,7))),
|
||||||
[0**1, 1**2, 2**3])
|
[0**1, 1**2, 2**3])
|
||||||
self.assertEqual(list(imap(None, 'abc', range(5))),
|
def tupleize(*args):
|
||||||
|
return args
|
||||||
|
self.assertEqual(list(imap(tupleize, 'abc', range(5))),
|
||||||
[('a',0),('b',1),('c',2)])
|
[('a',0),('b',1),('c',2)])
|
||||||
self.assertEqual(list(imap(None, 'abc', count())),
|
self.assertEqual(list(imap(tupleize, 'abc', count())),
|
||||||
[('a',0),('b',1),('c',2)])
|
[('a',0),('b',1),('c',2)])
|
||||||
self.assertEqual(take(2,imap(None, 'abc', count())),
|
self.assertEqual(take(2,imap(tupleize, 'abc', count())),
|
||||||
[('a',0),('b',1)])
|
[('a',0),('b',1)])
|
||||||
self.assertEqual(list(imap(operator.pow, [])), [])
|
self.assertEqual(list(imap(operator.pow, [])), [])
|
||||||
self.assertRaises(TypeError, imap)
|
self.assertRaises(TypeError, imap)
|
||||||
|
self.assertRaises(TypeError, list, imap(None, range(3), range(3)))
|
||||||
self.assertRaises(TypeError, imap, operator.neg)
|
self.assertRaises(TypeError, imap, operator.neg)
|
||||||
self.assertRaises(TypeError, next, imap(10, range(5)))
|
self.assertRaises(TypeError, next, imap(10, range(5)))
|
||||||
self.assertRaises(ValueError, next, imap(errfunc, [4], [5]))
|
self.assertRaises(ValueError, next, imap(errfunc, [4], [5]))
|
||||||
|
|
|
@ -12,6 +12,9 @@ What's New in Python 3.0a3?
|
||||||
Core and Builtins
|
Core and Builtins
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
|
- map() and itertools.imap() no longer accept None for the first argument.
|
||||||
|
Use zip() instead.
|
||||||
|
|
||||||
- Issue #1769: Now int("- 1") is not allowed any more.
|
- Issue #1769: Now int("- 1") is not allowed any more.
|
||||||
|
|
||||||
- Object/longobject.c: long(float('nan')) raises an OverflowError instead
|
- Object/longobject.c: long(float('nan')) raises an OverflowError instead
|
||||||
|
|
|
@ -1490,31 +1490,6 @@ imap_traverse(imapobject *lz, visitproc visit, void *arg)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
imap() is an iterator version of __builtins__.map() except that it does
|
|
||||||
not have the None fill-in feature. That was intentionally left out for
|
|
||||||
the following reasons:
|
|
||||||
|
|
||||||
1) Itertools are designed to be easily combined and chained together.
|
|
||||||
Having all tools stop with the shortest input is a unifying principle
|
|
||||||
that makes it easier to combine finite iterators (supplying data) with
|
|
||||||
infinite iterators like count() and repeat() (for supplying sequential
|
|
||||||
or constant arguments to a function).
|
|
||||||
|
|
||||||
2) In typical use cases for combining itertools, having one finite data
|
|
||||||
supplier run out before another is likely to be an error condition which
|
|
||||||
should not pass silently by automatically supplying None.
|
|
||||||
|
|
||||||
3) The use cases for automatic None fill-in are rare -- not many functions
|
|
||||||
do something useful when a parameter suddenly switches type and becomes
|
|
||||||
None.
|
|
||||||
|
|
||||||
4) If a need does arise, it can be met by __builtins__.map() or by
|
|
||||||
writing: chain(iterable, repeat(None)).
|
|
||||||
|
|
||||||
5) Similar toolsets in Haskell and SML do not have automatic None fill-in.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
imap_next(imapobject *lz)
|
imap_next(imapobject *lz)
|
||||||
{
|
{
|
||||||
|
@ -1536,8 +1511,6 @@ imap_next(imapobject *lz)
|
||||||
}
|
}
|
||||||
PyTuple_SET_ITEM(argtuple, i, val);
|
PyTuple_SET_ITEM(argtuple, i, val);
|
||||||
}
|
}
|
||||||
if (lz->func == Py_None)
|
|
||||||
return argtuple;
|
|
||||||
result = PyObject_Call(lz->func, argtuple, NULL);
|
result = PyObject_Call(lz->func, argtuple, NULL);
|
||||||
Py_DECREF(argtuple);
|
Py_DECREF(argtuple);
|
||||||
return result;
|
return result;
|
||||||
|
@ -1547,10 +1520,7 @@ PyDoc_STRVAR(imap_doc,
|
||||||
"imap(func, *iterables) --> imap object\n\
|
"imap(func, *iterables) --> imap object\n\
|
||||||
\n\
|
\n\
|
||||||
Make an iterator that computes the function using arguments from\n\
|
Make an iterator that computes the function using arguments from\n\
|
||||||
each of the iterables. Like map() except that it returns\n\
|
each of the iterables. Stops when the shortest iterable is exhausted.");
|
||||||
an iterator instead of a list and that it stops when the shortest\n\
|
|
||||||
iterable is exhausted instead of filling in None for shorter\n\
|
|
||||||
iterables.");
|
|
||||||
|
|
||||||
static PyTypeObject imap_type = {
|
static PyTypeObject imap_type = {
|
||||||
PyVarObject_HEAD_INIT(NULL, 0)
|
PyVarObject_HEAD_INIT(NULL, 0)
|
||||||
|
|
|
@ -815,7 +815,6 @@ 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\
|
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\
|
the function is called with an argument list consisting of the\n\
|
||||||
corresponding item of each iterable, until an iterable is exhausted.\n\
|
corresponding item of each iterable, until an iterable is exhausted.\n\
|
||||||
If the function is None, 'lambda *a: a' is assumed.\n\
|
|
||||||
(This is identical to itertools.imap().)");
|
(This is identical to itertools.imap().)");
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue