Why does the Google Python Style Guide prefer list comprehensions and for loops instead of filter, map, and reduce?
Deprecated Language Features: ... \"Use list com
List comprehensions are generally considered more "pythonic" than filter
, map
and reduce
.
See also this article by Python creator Guido van Rossum.
As far as filing this under "Deprecated Language Features" in the style guide, there were apparently plans to deprecate filter
, map
and reduce
in Python 3 (see the article referenced above).
Some of these plans changed eventually. reduce
was dropped from being a built-in function (and moved to the functools
module), but filter
and map
are still available as built-ins.
map
and filter
are way less powerful than their list comprehension equivalent. LCs can do both filtering and mapping in one step, they don't require explicit function and can be compiled more efficiently because of their special syntax
# map and filter
map(lambda x:x+1, filter(lambda x:x%3, range(10)))
# same as LC
[x+1 for x in range(10) if x%3]
There is simply no reason to prefer map or filter over LCs.
reduce
is slightly different, because there is no equivalent LC, but it has no big advantage over a ordinary for-loop either.
The Google Python Style guide does not say
prefer list comprehensions and for loops instead of filter, map, and reduce
Rather, the full sentence reads,
Use list comprehensions and for loops instead of filter and map when the function argument would have been an inlined lambda anyway. (my emphasis)
So it is not recommending that you completely avoid using map
, for instance -- only that
[expression(item) for item in iterable]
is preferable to
map(lambda item: expression(item), iterable)
In this case it is clear that the list comprehension is more direct and readable.
On the other hand, there is nothing wrong with using map
like this:
map(str, range(100))
instead of the longer-winded
[str(item) for item in range(100)]
It performs well to boot:
In [211]: %timeit list(map(str,range(100)))
7.81 µs ± 151 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [215]: %timeit [str(item) for item in range(100)]
10.3 µs ± 3.06 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
I would think that it is because not everybody knows how to use those functions well; readability may be impaired for people who are not as familiar. Also, the for
loop and list comprehension are widely used and easy to understand; even though the latter is from functional programming, just like map
, filter
, and reduce
, it mirrors lists and for
loops quite well. In any case, cramming a lambda or defining a function just to use with map, filter, or reduce can get annoying, especially since a lambda can only be a single expression and a function could clutter your code. You don't need them anyways; map(func, seq)
is just [func(x) for x in seq]
and filter
is just a list comprehension with an if
component. reduce
can be done with a for
loop.
In short, for
and list comprehensions are clearer, and they provide basically equivalent functionality in most cases.