开发者

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 and row. 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).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜