[Python-ideas] About list comprehension syntax

Terry Reedy tjreedy at udel.edu
Wed May 30 18:30:47 CEST 2007


"Arnaud Delobelle" <arno at marooned.org.uk> wrote in 
message news:8C1BDF74-1DAB-4F64-A28E-16788C48AA95 at 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






More information about the Python-ideas mailing list