PEP 284, Integer for-loops (fwd)
Tim Peters
tim.one at comcast.net
Mon Mar 11 22:33:01 EST 2002
[Tim]
>> 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)
[James Althoff]
> 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).
I didn't have subclassing in mind; e.g.,
class Table:
def __init__(self, table):
self.t = table
def rows(self):
return RowIterator(self.t)
def cols(self):
return ColIterator(self.t)
class Element:
def __init__(self, table, i, j):
self.t, self.i, self.j = table, i, j
def get(self):
return self.t.getValueAt(self.i, self.j)
def set(self, value):
self.t.setValueAt(self.i, self.j, value)
purely in Python. Your original table type is incorporated by containment
here, not subclassing. Now you just need to define RowIterator and
ColIterator. For example, picking on rows, and in a way that makes "a row"
an object in its own right:
class RowIterator:
def __init__(self, table):
self.t = table
# Unclear whether these guys are 0-based or 1-based.
# This assumes 0-based. Fiddle accordingly.
self.limit = table.getRowCount()
def __getitem__(self, i):
if 0 <= i < self.limit:
return Row(self.t, i)
else:
raise IndexError
class Row:
def __init__(self, table, i):
self.t, self.i = table, i
def get(self, j):
return self.t.getValueAt(self.i, j)
def set(self, j, value):
self.t.setValueAt(self.i, j, value)
def elements(self):
return RowElementIterator(self.t, self.i)
class RowElementIterator:
def __init__(self, table, i):
self.t, self.i = table, i
self.limit = table.getColumnCount()
def __getitem__(self, j):
if 0 <= j < self.limit:
return Element(self.t, self.i, j)
else:
raise IndexError
That implements more than the example at the start actually needs; cut back
to taste <wink>.
> 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.
The new iterator stuff makes coding this kind of thing clearer and easier,
but the visible *interface* need not change at all. This is actually
well-suited to the __getitem__ protocol: that was designed with sequential
indexing in mind, and that's what you're doing here The new iterator
protocol is an enormous improvement only when sequential indexing is a
strain (like, e.g., in tree traversal).
> ...
> 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.
I'd try a dict, mapping types to unbound methods, like:
rowcounter = {JTable: JTable.getRowCount,
DefaultTableModel: DefaultTableModel.getRowCount,
ThirdPartyBozo: ThirdPartyBozo.getNumberOfRows}
def ri(table):
"Return indices of table rows."
return range(rowcounter[type(table)](table))
I don't know whether that works exactly as-is in Jython, but you get the
idea. Unless you have an unbounded number of classes (a bad Smalltalk habit
you should have given up by now <wink>), using dicts to add "conceptual
members" to classes is an effective technique.
there's-more-than-one-to-do-indirection-in-python-ly y'rs - tim
More information about the Python-list
mailing list