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


--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to