[Python-Dev] Use for enumerate()
Tim Peters
tim.one@comcast.net
Fri, 26 Apr 2002 20:56:31 -0400
[Guido]
> Here's a cute use for enumerate(), now that it's checked in.
> ...
> A function that reads forward until the right line is of course easily
> written for any version of Python; but enumerate() seems a
> particularly good fit here since it avoids the need to have a separate
> counter. This also shows how useful it is that files are iterators!
>
> def getline(filename, lineno):
> if lineno < 1:
> return ''
> lineno -= 1
> f = open(filename)
> for i, line in enumerate(f):
> if i == lineno:
> break
> else:
> line = ''
> f.close()
> return line
>
> Challenge 1: do it faster.
Challenge 0: Stop posting Python code with stinking tabs <wink>.
The attached g2 is about 60% quicker across the text files I tried it on,
using this timing driver (which sums the time across all interesting inputs;
note that, overall, this is quadratic-time in the number or lines for either
method):
FNAME = "whatever"
def drive():
from time import clock as now
f = file(FNAME)
n = len(f.readlines())
f.close()
indices = range(n+2)
for func in getline, g2:
start = now()
for i in indices:
func(FNAME, i)
finish = now()
print func.__name__, finish - start
> Challenge 2: do it with less code.
Measured by bytes, lines, statements, or conceptual pain <wink>?
> Challenge 3: do it faster and with less code.
That's a tough one.
Here's g2. It's a non-ambitious member of the "reduce the number of trips
around the eval loop" school of optimization:
def g2(filename, lineno):
offset = lineno - 1
if offset < 0:
return ''
line = ''
f = file(filename)
lines = True
while lines:
lines = f.readlines(5000)
n = len(lines)
if offset >= n:
offset -= n
continue
line = lines[offset]
break
f.close()
return line