PEP 284, Integer for-loops (fwd)
James_Althoff at i2.com
James_Althoff at i2.com
Mon Mar 11 18:17:38 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.
[Tim Peters]
> Hmm. The inability to pass a new value to setValueAt seems to make
> this a little feeble <wink>.
Ah, but is it feeble or is it *omniscient*?
Actually, I did it this way just to be consistent; I make the same mistake
when I type it in code, too.
The suggestions below are nice -- although our particular (Java-based)
context leaves us still with a few spanners to deal with.
> 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)
This is nice. We have noticed that there can be a hit in Jython the first
time you instantiate a Python subclass of a Java class (it seems to build
some internal structures based on a lot of Java reflection). We could
implement a Java subclass instead. But we are trying to minimize the
appearance of needing to resort back to Java for what are probably obvious
reasons. But I think it might be worth having this option for times when
performance isn't an issue and looping through all rows or columns is
required. I would rather do it with the new iterator stuff that is
available in C-Python, but ... oh well.
> 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.
Some helper functions might be convenient. They would be most convenient
in a helper utility module, of course, so that we could standardize them
for the entire development team. A twist that we have to live with is that
the 3rd party components are not always consistent with each other. JTable
and DefaultTableModel both use "getRowCount()". So we could have a generic
function for these. But another 3rd party component uses "getNumberOfRows
()" instead. So we would have to do the try:except:/hasattr/isinstance
stuff to make the helper functions generic. Probably worth giving it a
try.
> 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).
Thanks for the suggestions.
Jim
More information about the Python-list
mailing list