views:

166

answers:

3

I am using a module that is part of a commercial software API. The good news is there is a python module - the bad news is that its pretty unpythonic.

To iterate over rows, the follwoing syntax is used:

cursor = gp.getcursor(table)
row =  cursor.next()
while row:
    #do something with row
    row = cursor.next()

What is the most pythonic way to deal with this situation? I have considered creating a first class function/generator and wrapping calls to a for loop in it:

def cursor_iterator(cursor):
    row =  cursor.next()
    while row:
        yield row
        row = cursor.next()

[...]

cursor = gp.getcursor(table)
for row in cursor_iterator(cursor):
    # do something with row

This is an improvement, but feels a little clumsy. Is there a more pythonic approach? Should I create a wrapper class around the table type?

+10  A: 

Assuming that one of Next and next is a typo and they're both the same, you can use the not-so-well-known variant of the built-in iter function:

for row in iter(cursor.next, None):
    <do something>
Paul Hankin
Great answer! Yep, the functions are the same (worse still, they are somehow case insensitive!).
fmark
pretty elegant!
pygabriel
+1  A: 

The best way is to use a Python iterator interface around the table object, imho:

class Table(object):
    def __init__(self, table):
         self.table = table

    def rows(self):
        cursor = gp.get_cursor(self.table)
        row =  cursor.Next()
        while row:
            yield row
            row = cursor.next()

Now you just call:

my_table = Table(t)
for row in my_table.rows():
     # do stuff with row

It's very readable, in my opinion.

Olivier
+2  A: 

You could create a custom wrapper like:

class Table(object):
    def __init__(self, gp, table):
        self.gp = gp
        self.table = table
        self.cursor = None

   def __iter__(self):
        self.cursor = self.gp.getcursor(self.table)
        return self

   def next(self):
        n = self.cursor.next()
        if not n:
             raise StopIteration()
        return n

and then:

for row in Table(gp, table)

See also: Iterator Types

Felix Kling
I like this approach also. I might consider wrapping `gp` in this manner if I need to wrap more than just the cursor iteration.
fmark