Nested iteration?
Terry Jan Reedy
tjreedy at udel.edu
Tue Apr 23 16:49:30 EDT 2013
On 4/23/2013 11:40 AM, Roy Smith wrote:
> In reviewing somebody else's code today, I found the following
> construct (eliding some details):
>
> f = open(filename)
> for line in f:
> if re.search(pattern1, line):
> outer_line = f.next()
> for inner_line in f:
> if re.search(pattern2, inner_line):
> inner_line = f.next()
Did you possibly elide a 'break' after the inner_line assignment?
> Somewhat to my surprise, the code worked.
Without a break, the inner loop will continue iterating through the rest
of the file (billions of lines?) looking for pattern2 and re-binding
inner-line if there is another line or raising StopIteration if there is
not. Does this really constitute 'working'?
This is quite aside from issue of what one wants if there is no pattern1
or if there is no line after the first match (probably not
StopIteration) or if there is no pattern2.
> I didn't know it was legal to do nested iterations over the same iterable
Yes, but the effect is quite different for iterators (start where the
outer iteration left off) and non-iterators (restart at the beginning).
r = range(2)
for i in r:
for j in r:
print(i,j)
# this is a common idiom to get all pairs
0 0
0 1
1 0
1 1
ri= iter(range(3))
for i in ri:
for j in ri:
print(i,j)
# this is somewhat deceptive as the outer loop executes just once
0 1
0 2
I personally would add a 'break' after 'outer_line = next(f)', since the
first loop is effectively done anyway at that point, and dedent the
second for statement. I find to following clearer
ri= iter(range(3))
for i in ri:
break
for j in ri:
print(i,j)
# this makes it clear that the first loop executes just once
0 1
0 2
I would only nest if the inner loop could terminate without exhausting
the iterator and I wanted the outer loop to then resume.
__
Terry Jan Reedy
More information about the Python-list
mailing list