On Thu, 17 Aug 2017 03:54 pm, Marko Rauhamaa wrote: > Ben Finney <ben+pyt...@benfinney.id.au>: > >> The Python list comprehension syntax does not specify control flow. > > I understand your point, but how do you know your statement is true? > > I didn't check this, but I would imagine the list comprehension: > > [ f(x) for x in I if c(x) ] > > was defined as syntactic sugar for: > > list(f(x) for x in I if c(x))
Not originally. List comprehensions were added to Python in version 2.0, before generator expressions. (Generator expressions only made it into the language in version 2.4.) But right from 2.0, they have been explicitly defined as equivalent to for loops: https://github.com/python/cpython/blob/6f0eb93183519024cb360162bdd81b9faec97ba6/Doc/whatsnew/2.0.rst#list-comprehensions In Python 3, it would make sense for list/set/dict comprehensions to be thin wrappers around generator expressions, but I don't know if they share implementations that way or have separate "copy and paste" implementations. I can't find where they are implemented. This does leave a *tiny* bit of wriggle-room: the implementation (in C, say, or some other language) doesn't have to use a for-loop. It could use recursion, or a while-loop, or it might unroll the loop into a long series of imperative statements, or use GOTO to emulate looping. So long as the Python semantics remain the same, and the elements are generated in the same order. > where > > f(x) for x in I if c(x) > > has heavily iterative semantics. Indeed. For loops are one of the cardinal examples of iteration. It isn't a coincidence that generator expressions and comprehensions use the same syntax. Whatever implementation is used, the semantics must be the same as the equivalent for loop procedural code. For example: from io import StringIO myfile = StringIO('Is this the room for an argument?') values = [myfile.read(1) for i in range(33)] assert values == list('Is this the room for an argument?') Python is not free to generate the results in some other order. >> List comprehensions, in their syntax, strongly connote a single >> declarative operation. This makes them different from iteration >> syntax. > > Except for side effects, you get the same result whichever way you > imagine it. That's not correct, as the example of reading from a file demonstrates. > As a side not, I have found it rather confusing that I have to say: > > [ (x, y) for x in range(5) for y in range(x) ] > > instead of: > > [ (x, y) for y in range(x) for x in range(5) ] That doesn't work because x isn't defined when you call range(x). > After all, you must say: > > [ ((x, y) for y in range(x)) for x in range(5) ] > > which, admittedly, means a different thing. Indeed. Completely different. -- Steve “Cheer up,” they said, “things could be worse.” So I cheered up, and sure enough, things got worse. -- https://mail.python.org/mailman/listinfo/python-list