[Tutor] Nested list comprehensions

Alan Gauld alan.gauld at freenet.co.uk
Sat May 6 01:55:41 CEST 2006


> I am having trouble wrapping my mind around
> nested list comprehensions

I do too, and usually when that happens I take it as a sign
that I'm being too clever for my own good. I unwrap things
back to the point where my brain doesn't hurt anymore...

I think I've only seen two or three nested comprehensions
that I could easily read. Mostly they should be avoided IMHO!

> I have a list of objects C1 and each object in the list has
> a method m() that will return a list of sub-objects.
> I would like to create a list that contains all
> sub-objects of all members of the C1 collection.

> If I weren't trying to use list comprehensions, I would code this 
> as:
>
> result = []
> for eachObject in C1:
>    for eachSubObject in eachObject.m():
>        result.append(eachSubObject)

Which makes perfect sense and is definitely the way I'd go.
However...

> result = [eachSubObject for eachObject in C1 for eachSubObject in 
> eachObject.m()]

Yep, that looks right to me.

> I am already expecting the "just use the first syntax if that does 
> what you want"
> answers - but in this case, I am trying to understand nested list 
> comprehensions,
> so I would appreciate an explanation of the list comprehension 
> syntax.

Since you want to understand the syntax...

[<expression>
     for item1 in sequence1
     for item2 in sequence2...
     for itemN in sequenceN
         <condition>]

So your LC becomes:

[eachSubObject
     for eachObject in C1
     for eachSubObject in eachObject.m()
]

> If this _is_ the correct syntax, this reads very awkwardly to me,

Does the layout above look any better?
I find breaking nested LCs doen into that structure makes them
easier to figure out.

> and my initial reaction to this is that it should be expressed as:
>
> result = [eachSubObject for eachSubObject in eachObject.m() for 
> eachObject in C1]

My take on that is that it doesn't work from a scoping point of view.
You have to fetch eachObject before you can send m() to it.
Doing it the way you have it here would involve calling
eachObject.m() before eachObject had been fetched from C1

> However, in my testing, this doesn't appear to work.
> If somone has a way of reading the nested list comprehension
> syntax that makes sense, I would appreciate it if you would share 
> it.

I dunno if my ramblings help, but its how I read nested LOCs when
I'm forced into that situation.

Alan Gauld
Author of the Learn to Program web site
http://www.freenetpages.co.uk/hp/alan.gauld 




More information about the Tutor mailing list