I was having some trouble grokking the list comprehension syntax in Python, so I started thinking about how to achieve the same thing in Perl, which I'm more familiar with. I realized that the basic examples (taken from this page) can all be done in Perl with map
or grep
.
E.g.
(python) (perl)
S = [x**2 for x in range(10)] @S = map { $_**2 } ( 0..9 );
V = [2**i for i in range(13)] @V = map { 2**$_ } ( 0..12 );
M = [x for x in S if x % 2 == 0] @M = grep { $_ % 2 == 0 } @S;
So is "list comprehension" just a fancy term for "map and/or filter a list" or is there more to it?
List comprehensions are often described as being more Pythonic than loops or map() . But rather than blindly accepting that assessment, it's worth it to understand the benefits of using a list comprehension in Python when compared to the alternatives.
List comprehension is more concise and easier to read as compared to map. List comprehension are used when a list of results is required as map only returns a map object and does not return any list. Map is faster in case of calling an already defined function (as no lambda is required).
Map function is faster than list comprehension when the formula is already defined as a function earlier. So, that map function is used without lambda expression.
List comprehension works with string lists also. The following creates a new list of strings that contains 'a'.
You are correct: a list comprehension is essentially just syntactic sugar for map and filter (terms from the functional programming world).
Hopefully this sample code demonstrates their equality:
>>> # Python 2
>>> [x**2 for x in range(10)] == map(lambda x: x**2, range(10))
True
>>> [2**i for i in range(13)] == map(lambda x: 2**x, range(13))
True
>>> S = [x**2 for x in range(10)]
>>> [x for x in S if x % 2 == 0] == filter(lambda x: x % 2 == 0, S)
True
Note that this is only valid in Python 2.X, as SilentGhost pointed out in the comment. To make this compatible with Python 3, you'll have to wrap the calls to map or filter in the list
constructor, because map and filter have been updated to return iterators, not lists.
>>> # Python 3
>>> [x**2 for x in range(10)] == list(map(lambda x: x**2, range(10)))
True
>>> [2**i for i in range(13)] == list(map(lambda x: 2**x, range(13)))
True
>>> S = [x**2 for x in range(10)]
>>> [x for x in S if x % 2 == 0] == list(filter(lambda x: x % 2 == 0, S))
True
Yes, they are basically the same.
In fact Python also has a map function:
S = map(lambda x: x**2, range(10))
is the same as your first examples above. However, the list comprehension syntax is strongly preferred in Python. I believe Guido has been quoted as saying he regrets introducing the functional syntax at all.
However, where it gets really interesting is in the next evolution of list comprehensions, which is generators. These allow you to return an iterator - rather than processing the whole list at once, it does a single iteration and then returns, so that you don't have to hold the whole list in memory at the same time. Very powerful.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With