What's a neater, more pythonic way to do the following enumeration?
for row, instrument in enumerate(instruments):
for col, valu开发者_如何学Pythone in enumerate(instrument):
self.table.SetValue(row, col, value)
What you are calling row
is not a row, it is a row index. instrument
is a row. Apart from that:
If the only tool that you have is a SetValue(row_index, column_index, value)
method and that method does more than help replicate the structure of instruments
laboriously, and the instruments
collection is as your code describes, then there is no better way. It is already much better than
#WARNING: BAD PRACTICE! DON'T USE THIS CODE!
for row_index in xrange(len(instruments)):
instrument = instruments[row_index]
for column_index in xrange(len(instrument)):
self.table.SetValue(row_index, column_index, instrument[column_index])
or any perversion thereof.
Otherwise you may be interested in import copy; self.table = copy.copy(instruments)
or even (as SilentGhost has suggested) self.table = instruments
You've mentioned in the comments that this loop is a part of asynchronous function (in terms of twisted framework). In this case you don't want to block for a long time:
from twisted.internet import task
for i, row in enumerate(instruments):
task.coiterate(self.table.SetValue(i, j, v) for j, v in enumerate(row))
Thus all rows are assigned in parallel.
NOTE:
- Watch out for late binding for
i
androw
. Use(lambda i=i, row=row: ...)()
in that case. task.coiterate()
uses global object therefore there could be multiple table updates simultaneously (it might not be what you want).
Here's @SilentGhost' answer (deleted):
self.table = instruments
Because that's what you seem to be doing.
And the comment by @[Ben Hughes] I'm referring to:
I need to explicity call SetValue (its on a PyGridTableBase) for each value - as this code is invoked via a twisted deferred method - my brain is not much good at looping/enumeration in a neat way..... – Ben Hughes
The fundamental question is not regarding this loop.
The fundamental questions are these:
1) Where does this instruments
structure come from, and why do you need to reorganize it?
2) What is this self.table
structure on which you're calling SetValue
?
3) What are you going to do with this self.table
structure?
Until you answer these questions, your sample Python code has no context in which it can be evaluated. It's just code.
One option is using a list comprehension:
[self.table.setValue(row, col, value)
for row, instrument in enumerate(instruments)
for col, value in enumerate(instrument)]
Not sure if it is any neater or more pythonic... But it is another way of expressing the loop.
One could argue that the list comprehension is clearer, since the "action" part (setValue) is placed first/at the top. Instead of being buried inside the loop.
EDIT:
Yet another way, using a helper function and a generator expression:
def loop(iterator):
for item in iterator: pass
loop(self.table.setValue(row, col, value)
for row, instrument in enumerate(instruments)
for col, value in enumerate(instrument))
The helper function can be the built-in any() if you know for certain that the loop body will never evaluate to True in a boolean context (any() will stop the iteration on the first True).
精彩评论