End of file

Alex Martelli aleaxit at yahoo.com
Thu Oct 7 09:44:08 EDT 2004


Andreas Kostyrka <andreas at kostyrka.org> wrote:
   ...
> > for counter, line in enumerate(f):
> >     if counter == lines-1: is_last_line(line)
> >     else: is_ordinary_line(line)
> > 
> > If the file's possibly too big to read comfortably in memory, of course,
> > other suggestions based on generators &c are preferable.

> This should do it "right":
> 
> f = file("/etc/passwd")
> fi = iter(f)
> 
> def inext(i):
>     try:
>         return i.next()
>     except StopIteration:
>         return StopIteration
> 
> next = inext(fi)
> while next <> StopIteration:
>     line = next
>     next = inext(fi)
>     if next == StopIteration:
>         print "LAST USER", line.rstrip()
>     else:
>         print "NOT LAST", line.rstrip()

I think the semantics are correct, but I also believe the control
structure in the "application code" is too messy.  A generator lets you
code a simple for loop on the application side of things, and any
complexity stays where it should be, inside the generator.  Haven't read
the other posts proposing generators, but something like:

def item_and_lastflag(sequence):
    it = iter(sequence)
    next = it.next()
    for current in it:
        yield next, False
        next = current
    yield next, True

lets you code, application-side:

for line, is_last in item_and_lastflag(open('/etc/passwd')):
    if is_last: print 'Last user:', line.rstrip()
    else print: 'Not last:', line.rstrip()

Not only is the application-side loop crystal-clear; it appears to me
that the _overall_ complexity is decreased, not just moved to the
generator.


Alex



More information about the Python-list mailing list