
"Arnaud Delobelle" <arno@marooned.org.uk> wrote in message news:8C1BDF74-1DAB-4F64-A28E-16788C48AA95@marooned.org.uk... | Hi | | List comprehensions (and generator expressions) come in two | 'flavours' at the moment: Actually, you can have 1 to many for clauses and 0 to many if clauses. | (1) [f(x) for x in L], which stands for map(f, L). Let's call this a | 'map comprehension' | | (2) [f(x) for x in L if p(x)], which stands for map(f, filter(p, L)). | Let's call this a 'map-filter comprehension'. | | Now if one wants to write simply filter(p, L) as a list | comprehension, one has to write: | | (3) [x for x in L if p(x)]. This could be called a 'filter | comprehension'. | | the 'x for x in L' is not very nice IMHO, but it is often handy to | use such expressions over 'filter(...)', eg building the sublist of a | given list consisting of all the items of a given type could be | written as: | | filter(lambda x: isinstance(x, FilteringType), heterogeneous_list) | | or: | | [x for x in heterogenous_list if isinstance(x, FilteringType)] | | I still prefer the list comprehension over the lambda/filter | combination, but neither feels very satisfying (to me :) (not that | one cannot use partial in the filter version) | | Why not just drop the 'x for' at the start of a 'filter | comprehension' (or generator expression)? Because such micro abbreviations are against the spirit of Python, which is designed for readability over writablilty. Even for a writer, it might take as much time to mentally deal with the exception and to simply type 'for x', which takes all of a second. Also, this breaks the mapping between for/if statements and clauses and makes the code ambiguous for both humans and the parser | Thus (3) could be written more simply as: | | (3') [x in L if p(x)] (x in L) is a legal expression already. (x in L) if p(x) looks like the beginning of (x in L) if p(x) else 'blah' . The whole thing looks like a list literal with an incompletely specified one element. | This is consistent with common mathematical notation: 'Common mathematical notation' is not codified and varies from writer to writer and even within the work of one writer. Humans make do and make guesses, but parser programs are less flexible. | * { f(x) | x \in L } means the set of all f(x) for x in L | * { f(x) | x \in L, p(x) } means the set of all f(x) for x in L | satisfying predicate p. | * { x \in L | p(x) } means the set of all x in L satisfying predicate p. I personally do not like the inconsistency of the last form, which flips '\in L' over the bar just because f(x) is the identify function. It would be OK though in a situation where that was the only set comprehension being used. But that is not the case with Python. Terry Jan Reedy