That said, I've started to consciously cut back on my use of list comprehensions. They are powerful, but there's a temptation to cram too much into one line - which makes debugging harder, and reduces readability. Breaking things out into a for loop often makes things clearer again.
This is actually one of my big gripes with Python: loops don't scale.
If I've got something small, it looks great to say [f(x) for x in Y], and then I add "...if x.z > m", and then I add something else, and 10 minutes later I say "ugh, too much!", and have to rewrite it as a for-loop. If I want to add a "print" in there while I'm experimenting, I'm completely SOL (yes, I know about 3.0a). The final form of a loop might not look anything like its initial form, even though they're nearly identical, both to me and to the computer.
In Common Lisp, in contrast, I can start with (loop for x in Y collect (f x)), and then add clauses all day -- LOOP, for all of its flaws, scales great from a couple words of pseudo-English surrounded by a pair of parens, up to just about anything that can be expressed as a loop. (CL-ITERATE might be even better, but I haven't gotten around to learning it yet.)
Maybe if I had an Emacs function to convert between list comprehensions and for-loops this wouldn't bug me so much.
True. I think it might also be generally possible to pull a mapping function and a filtering function out of any list comprehension or generator expression. That helps with debugging, too, without hurting performance:
def crazy_mapping(var): ...
def crazy_filter(var): ...
foo = [crazy_mapping(b) for b in bar if crazy_filter(b)]
That said, I've started to consciously cut back on my use of list comprehensions. They are powerful, but there's a temptation to cram too much into one line - which makes debugging harder, and reduces readability. Breaking things out into a for loop often makes things clearer again.