问题
Python's map
can take multiple iterables, for use when the callable can accept the same number of input arguments. If the input iterables are the same length, thats behaving like the list comprehension passing in zipped arguments, e.g.:
>>> iterables = 'spam', 'eggs'
>>> map(max, *iterables)
['s', 'p', 'g', 's']
>>> [max(*a) for a in zip(*iterables)]
['s', 'p', 'g', 's']
When the input arguments are different length, it gets weird - Python 2 (docs) pads with None
, but Python 3 (docs) truncates to shortest iterable.
>>> map(max, 'spam', 'potato') # 2.x
['s', 'p', 't', 'm', 't', 'o']
>>> list(map(max, 'spam', 'potato')) # 3.x
['s', 'p', 't', 'm']
Why is this feature existing, what's an example of a typical case where that's needed or useful? I don't know a lot about functional styles, could I be missing out on some great strengths of map
that are related to the multiple arguments? And what's the rationale for the API change in 3.x?
回答1:
Regarding why map
truncates in python3, this is simply because python3's map
is actually itertools.imap. And the documentation says:
Like
map()
but stops when the shortest iterable is exhausted instead of filling inNone
for shorter iterables. The reason for the difference is that infinite iterator arguments are typically an error formap()
(because the output is fully evaluated) but represent a common and useful way of supplying arguments toimap()
.
The truncation allows you to do things like map(func, itertools.repeat(5), [1,2,3])
and iterate over the result without worries. With the old map
that would be an infinite loop.
One of the most significant changes in python3 is that a lot of built-in functions now return generators instead of list
s, including map
and zip
. This "increased lazyness" changed the way these functions should be used and thus the modified behaviour.
As to why one would ever use python2's multiple-iterables to map
I don't know. Sure, it's a shortcut for something like (in python3):
list(itertools.starmap(function, itertools.zip_longest(*iterables)))
This might have some corner case usage, but I've never seen it used.
Probably most people don't even know that map
accepts a sequence of iterables.
So, AFAIK there isn't any super-power deriving from the use of multiple arguments.
As to why map
is in the language, that's because map
was there long before list-comprehensions. Before list-comprehensions it was quite useful for building lists.
It wasn't remove for backward compatibility and because many people actually like it,
although Guido did want to remove it.
To learn more about the history of map
, filter
and reduce
and other functional aspects, read: The History of Python: Origins of Python's "Functional" Features
来源:https://stackoverflow.com/questions/20646996/using-map-with-multiple-args