Much simplified version exactly as suggested Zoran Isailovski - no class needed either. Works as a very tutorial for list comprehensions :)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | def process_lines(fd, handler, cond=None):
"""
Process all lines in fd
if cond is not None, process only lines returning True for cond
"""
if cond is not None:
[ handler(line) for line in fd.readlines() if cond(line) ]
else:
[ handler(line) for line in fd.readlines() ]
if __name__ == '__main__':
import sys
fname = sys.argv[0]
def line_printer(line):
sys.stdout.write(line)
# print all lines containing 'if'
process_lines(file(fname), line_printer, lambda n: n.find('file') > -1)
lst = []
# read all lines to list
process_lines(file(fname), lst.append)
for line in lst:
sys.stdout.write(line)
|
Old LineReader class was thrown to /dev/null - fd will really be exhausted during each call of process(), so a simple method is enough. As Zoran Isailovski suggested, a plain list comprehension is enough. So process_method() is useful only for newbies not yet getting the hang of list comprehensions, but they should definitely look for them - they are concise, easy to learn and yet powerful.
DoTheSimplestThingThatCouldPossiblyWork. What your recipe does is basically
if handler is a sequence, or
if handler is callable. There is no need for more complications. Still, some general hints:
1) You don't need a class just to store fd. Using a class makes the impression that you could call process() many times, but you can't - the first call eats up all the lines. You get the same functionality with a function process(fd, handler, cond).
2) Replace "hasattr(handler, '__call__')" with "callable(handler)"
3) Avoid omnipotency (of parameters). The handler can be a list and a function today, tomorow it could also be another file to write to... That is generally not a good idea. Handler should be just a function, and that's it.
3a) Note that you can pass list.append as handler to get the same effect, buying elegance for speed.
List comprehensions are powerful. Yes, I know that with list comprehensions it is quick and easy to do such things. However, the intention was to provide easy-to-use wrapping which newbies can remember. Then again, cookbook is often for handy recipes and for teaching people to program in Python, and in that respect your list comprehensions are much better.
(I have to admit I use listcomprehensions nowadays for the kind of stuff described, because of their clarity).
readlines not necessary? Python file objects iterate on lines, so you can use:
This has the advantage of not reading the whole file into memory in advance.