These are my opinions; I don't claim any authority for them. I just don't find the proposed syntax as obvious and unambiguous as you do, and would like to explain why that is so. Ken Kundert writes:
In my experience it is exceptions and inconsistencies that consume 'working memory in the brain of humans'. By eliminating the distinction between list comprehensions and for loops we would be making the language simpler by eliminating an inconsistency.
I don't think of a comprehension as a for loop, I think of it as setbuilder notation (although of course I realize that since lists are sequences it has to be a for loop under the hood). So the claimed inconsistency here doesn't bother me. I realize it bothers a lot of people, but the proposed syntax is not obvious to me (ambiguous and inconsistent in its own way).
[T]he writing of the generator function represents a speed bump.
It used to be, for me, but it really isn't any more. Perhaps you might get used to it if you tried it. Harder to argue: the fact that Guido and Nick (inter alia) consider it good style to use named functions makes that point a hard sell (ie, you don't need to convince me, you need to convince them).
Whereas writing something like the following is simple, compact, quick, and obvious. There is no reason why it should not be allowed even though it might not always be the best approach to use:
for i in range(5) for j in range(5) for k in range(5): ...
To me, that is visually ambiguous with for i in (range(5) for j in (range(5) for k in range(5))): ... although syntactically the genexp requires the parentheses (and in fact is almost nonsensical!) I could easily see myself forgetting the parentheses (something I do frequently) when I *do* want to use a genexp (something I do frequently), with more or less hilarious results. As already mentioned: for i, j, k in itertools.product(range(5), range(5), range(5)): ... To me that is much clearer, because it expresses the rectangular shape of the i, j, k space. I would also stumble on for i in range(5) for j in range(i + 1): ... at least the first few times I saw it. Based on the English syntax of "for" (not to mention the genexp syntax), I would expect for j in range(i + 1) for i in range(5): ... If itertools.product is the wrong tool, then the loop bodies are presumably complex enough to deserve new indent levels. Note that simple filters like non_nil (see below) can easily be used, as long as the resulting set is still a product.
And I would really like to be able to write loops of the form:
for item in items if item is not None: ...
def non_nil(items): return (item for item in items if item is not None) for item in non_nil(items): ... I think that's very readable, so the only reason why that 2-line function needs to be syntax that I can see is your distaste for defining functions, and that of other Python programmers who think like you.