Welcome, guest | Sign In | My Account | Store | Cart

Much simplified version exactly as suggested Zoran Isailovski - no class needed either. Works as a very tutorial for list comprehensions :)

Python, 29 lines
 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.

4 comments

Zoran Isailovski 16 years, 6 months ago  # | flag

DoTheSimplestThingThatCouldPossiblyWork. What your recipe does is basically

[ line for line in fd.readlines() if cond(line) ]

if handler is a sequence, or

[ handler(line) for line in fd.readlines() if cond(line) ]

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.

Zoran Isailovski 16 years, 6 months ago  # | flag

3a) Note that you can pass list.append as handler to get the same effect, buying elegance for speed.

Edvard Majakari (author) 16 years, 6 months ago  # | flag

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).

Ori Peleg 16 years, 6 months ago  # | flag

readlines not necessary? Python file objects iterate on lines, so you can use:

[handler(line) for line in fd]

This has the advantage of not reading the whole file into memory in advance.

Created by Edvard Majakari on Wed, 18 May 2005 (PSF)
Python recipes (4591)
Edvard Majakari's recipes (4)

Required Modules

Other Information and Tasks