Status: Accepted
Owner: asmeurer
Labels: Type-Defect Priority-Medium
New issue 1841 by asmeurer: Replace map() with a list compression in most
cases
http://code.google.com/p/sympy/issues/detail?id=1841
If you've been programming in Python for long enough, you know about the
magic of list comprehensions. They can
make what would otherwise be a short for loop or a map() into a very
simple, easy to understand, one line
expression.
Before they were introduced, the best way to do this sort of thing was with
the use of map(), and probably a lambda
function. But anything that uses lambda is very difficult to read, and
map() even without lambda is harder to read
than a list compression in almost all cases.
So I think we should replace most instances of map in the code with a list
comprehension. The exception might be
the use of f, g, h = map(Function, 'fgh') in the docstrings. map(lambda…
is the worst in my opinion, and git gr
'map(lambda' reveals around 25 of these.
Of course, performance is also an issue. While we should test the
performance of each instance that we actually
change, here are some simple benchmarks:
###
First, cache the function and the list.
###
In [1]: def f(x):
...: return x**2
...:
In [2]: a = range(100)
In [4]: %timeit map(f, a)
10000 loops, best of 3: 128 us per loop
In [5]: %timeit [f(x) for x in a]
10000 loops, best of 3: 162 us per loop
###
So map is slightly faster in this case.
But what if we don't cache the function or the list, but use lambda instead?
###
In [8]: %timeit map(lambda x: x**2, range(100))
10000 loops, best of 3: 145 us per loop
In [9]: %timeit [x**2 for x in range(100)]
10000 loops, best of 3: 64.4 us per loop
###
The use of lambda actually makes map 2x slower than a list comprehension.
It becomes even clearer if we cache only the list.
###
In [10]: %timeit [x**2 for x in a]
10000 loops, best of 3: 58.9 us per loop
In [11]: %timeit map(lambda x: x**2, a)
10000 loops, best of 3: 158 us per loop
In [12]: %timeit map(lambda x: f(x), a)
10000 loops, best of 3: 246 us per loop
###
Which is 3x faster for list comprehensions, or 6x if lambda is used
unnecessarily, which it actually doesn't seem to be anywhere in sympy.
lambda is usually used to call a multi-argument function with map()
###
In [13]: def g(x, y):
....: return x**2*y
....:
In [14]: %timeit map(lambda x: g(x, 10), a)
1000 loops, best of 3: 313 us per loop
In [15]: %timeit [g(x, 10) for x in a]
10000 loops, best of 3: 212 us per loop
###
One last example I ran (x is a Symbol):
###
In [6]: %timeit [x**i for i in range(100)]
1000 loops, best of 3: 2.78 ms per loop
In [7]: %timeit map(lambda i: x**i, range(100))
1000 loops, best of 3: 2.81 ms per loop
I've already done this for ode.py in my WIP ode-coverage branch.
--
You received this message because you are listed in the owner
or CC fields of this issue, or because you starred this issue.
You may adjust your issue notification preferences at:
http://code.google.com/hosting/settings
--
You received this message because you are subscribed to the Google Groups
"sympy-issues" group.
To post to this group, send email to sympy-iss...@googlegroups.com.
To unsubscribe from this group, send email to
sympy-issues+unsubscr...@googlegroups.com.
For more options, visit this group at
http://groups.google.com/group/sympy-issues?hl=en.