PEP 284, Integer for-loops (fwd)

Tim Peters tim.one at comcast.net
Mon Mar 11 15:51:10 EST 2002


[James_Althoff at i2.com]
> ...
> But if your protocol is
>     def getRowCount(): pass
>     def getColumnCount(): pass
>     def getValueAt(rowIndex,columnIndex): pass
>     def setValueAt(rowIndex,columnIndex): pass
> then that option is not available.

Hmm.  The inability to pass a new value to setValueAt seems to make this a
little feeble <wink>.

Depending on how much overhead you're willing to bear, it's straightfoward
to write wrapper classes (even using the old for/__getitem__ protocol) such
that, e.g., adding 1 to every element in a table could be expressed via

t = Table(original_table)
for r in t.rows():
    for e in r.elements():
        e.set(e.get() + 1)

Short of that, you could at least reduce the clumsiness by defining helper
functions, like (assuming these are 0-based indices; fiddle to taste):

def ri(table):
    "Return row indices for table."
    return range(table.getRowCount())

def ci(table):
    "Return column indices for table."
    return range(table.getColumnCount())

and then

columns = ci(table)
for i in ri(table):
    for j in columns:
         table.setValueAt(i, j, table.getValueAt(i, j) + 1)

would save some typing yet be just as quick.  Add

def getter(table):
    "Return bound table.GetValueAt."
    return table.GetValueAt

def setter(table):
    "Return bound table.SetValueAt."
    return table.SetValueAt

and then

get, set = getter(table), setter(table)
columns = ci(table)
for i in ri(table):
    for j in columns:
         set(i, j, get(i, j) + 1)

would be about as fast as you can get in Python, short of defining a custom
"add 1 to element and then store it back" function.

If you're very concerned about speed, when you've got a choice the loop with
the largest trip count should be innermost (as true in Python as in any
other language, although this is clawing at what are usually third-order
effects).





More information about the Python-list mailing list