7 ms·
alist = [foo(word) for word in words if word.startswith('a')] alist = map(foo, filter(lambda word: word.startswith('a'), words)) Which reads better?
by blossoms 12y ago
alist = [foo(word) for word in words if word.startswith('a')]
alist = map(foo, filter(lambda word: word.startswith('a'), words))
Which reads better?
- lolpep8 12y agoMap and filter, of course; less syntactical noise, simple function semantics, and plenty of precedent and equivalents in all other languages.
- bluecalm 12y agoIt's not like list comprehensions lack equivalent in other languages. Let's take Haskell for example. Python lists comprehension could use a where clause from Haskell though so one could really pack everything into a one-liner :) (as it is now, list comprehensions requiring various references to result of a function call evaluate the function each time it's used)
- TheLoneWolfling 12y agoThose are not equivalent. You need to wrap the map in a list() call.
- omaranto 12y agoIn Python 3 you'd be right, but I think people still call mostly that language "Python 3" and mean Python 2 when they say "Python".
- RHSeeger 12y agoAdmittedly, my thought would be to chain the calls, not nest them: alist = words.filter(lambda word: word.startswith('a') .map(foo) That being said, my Python is limited and I don't know it filter/map are available as methods of a list. At the end of the day, there are cases where list comprehensions are much cleaner/understandable... and cases where the reverse is true.
- CmdrKrool 12y ago> I don't know it filter/map are available as methods of a list. They're not. Which is a shame in my opinion, because as you've written it you can clearly read the operations in the order they happen, ie. filter followed by map. Instead, you do have to do the second line of what blossoms wrote above. And I don't think it's possible to write a list comprehension that reads in execution order, either :(
- LyndsySimon 12y agoI don't use FP practices in Python much, but if I did I'd define the filter outside the map, like so: begins_with_a = lambda x: x.startswith('a') alist = map(foo, filter(begins_with_a, words))
- nilved 12y agoEven with named functions, Python's use of global functions instead of methods for iterators force you to read the expression from the inside out. I think Lisp languages nailed this with their threading macros, which allow natural left-to-right reading, but Ruby's strategy is better than Python's, too, while maintaining very similar syntax. ;; clojure (let [begins-with-a #(.startsWith % "a") foo #(do-some-stuff-with %)] (-> words (filter begins-with-a) (map foo)))) # ruby words.filter { |e| e.start_with?(?a) }.map { |e| foo(e) } It doesn't really make sense for things like `len` and `map` to be global functions in object-oriented languages.