4 ms·
> write a list comprehension (...) code just looks a lot cleaner and what you're doing is clearer. I know how to use list comprehensions, but often avoid using
by cuu508 12y ago
> write a list comprehension (...) code just looks a lot cleaner and what you're doing is clearer.
I know how to use list comprehensions, but often avoid using them and use the standard for loops. List comprehensions look nice and clean for small examples, but they can easily get long and become mentally hard to parse. I would rather go for three 30 character lines instead of one 90 character line.
- meowface 12y agoI'm a bit torn on it. In a case where you need to do a lot of nested appends, I've found that even a long list comprehension can be easier to read. You just have to be sure to properly indent it and break it up into multiple lines. My rule is that every extra `for` starts a new line, and sometimes moving the predicate to its own line when it's too long, too.
- cuu508 12y agoFor a concrete example, I was just recently converting a list-of-dicts into a dict-of-dicts. Here's an isolated snippet: http://pastebin.com/8q46bK0v http://pastebin.com/8q46bK0v To my eye, the list comprehension version is reasonable. But I like the imperative style better: it uses the most basic language features and at a glance you can tell what it does. My favourite is the dictionary comprehension version, it's the shortest but still conveys clearly what it's doing.
- meowface 12y agoYeah, I prefer the dict comprehension. I use dict comprehensions quite frequently in my own code as well.
- bkeroack 12y agoDepends on how you want to program: imperative vs functional. Personally I think list comprehensions are the most beautiful part of Python, though sometimes I use map() when I'm trying to be explicitly functional (I realize it's allegedly slower, etc). Generally I think list comprehensions are cleaner and allow you to write purer functions with fewer mutable variables. I disagree that deeply nested for loops are necessarily more readable.
- existencebox 12y agoDeeply nested I'd usually agree, but if you end up with deeply nested comprehensions as a result, in either case, you're probably better off with a little bit of restructuring/splitting things more functions to at least make the nesting cleaner to read. However, I think he was referring to if the conditionals/additional modifications needed to build your list get a bit excessive, so you'd have a like... [dostuffto(A) for A in alsodostuffto(LIST) if conditional(A)] (but with more complex operations at each step). Granted at that point you can argue that you should do just as my example shows and put the "dostuffto" into more encapsulated functions, but sometimes that doesn't seem like the right choice.
- SEJeff 12y agoMap is not allegedly slower, it is demonstrably slower. $ python -mtimeit -s'nums=range(10)' 'map(lambda i: i + 3, nums)' 1000000 loops, best of 3: 1.61 usec per loop $ python -mtimeit -s'nums=range(10)' '[i + 3 for i in nums]' 1000000 loops, best of 3: 0.722 usec per loop Function calls have overhead in python, list comprehensions are implemented knowing this fact and avoiding it so the heavy lifting ultimately happens in C code.
- bkeroack 12y agoFair enough. I said "allegedly" because I had never personally measured the performance difference. Even though you could construe map as "half as fast" (or twice as slow) as the equivalent comprehension, I don't see a difference of ~1 usec making any difference in my code thus far. Good to know, though.
- SEJeff 12y agoYup, for very large calculations, or certain use cases, it can make much larger differences. It all depends on your use case.
- colcarroll 12y agoAs you point out though, it depends on where the function is coming from: $ python -mtimeit -s'nums=range(10)' '[str(i) for i in nums]' 100000 loops, best of 3: 2.57 usec per loop $ python -mtimeit -s'nums=range(10)' 'map(str, nums)' 1000000 loops, best of 3: 1.88 usec per loop $ python -mtimeit -s'nums=range(10)' 'import math' '[math.sqrt(i) for i in nums]' 100000 loops, best of 3: 3.25 usec per loop $ python -mtimeit -s'nums=range(10)' 'import math' 'map(math.sqrt, nums)' 100000 loops, best of 3: 2.55 usec per loop
- thinkpad20 12y agoI agree. I try to use list comprehensions when I can, but the fact is that as soon as you have to do any sort of logic in your map, it quickly gets unwieldy. I'd much rather use a functional style in many of these cases, but python's syntax and crummy lambdas (as compared to what would be natural to do in say JavaScript or Ruby), means that in the majority of cases I find myself using an imperative style.