2 ms·
In practice, quitRequested and processNextEvent are probably both members of some managerial object; perhaps like this: while not loop.quit_requested:
by chrismorgan 5y ago
In practice, quitRequested and processNextEvent are probably both members of some managerial object; perhaps like this:
while not loop.quit_requested:
process(loop.next_event())
And when you see it like that, then it becomes more apparent there’s an obvious way for it to be an iterator:
for event in loop.run():
process(event)
This is typically harder to get wrong, and generally matches the semantics of what you’re trying to do more closely: process a stream of events. You didn’t actually care about quit_requested, you cared about the events.
And so in this you can start to see why iterator-based for loops are normally better than while loops (and C-style for loops, which Python doesn’t support): while loops (and C-style for loops) are generic bookkeeping, with no specific semantics on the while condition (or for init/condition/increment clauses); but iterator-based for loops operate on actual data.
This principle can be seen in resource locking also; you don’t want a lock object beside the data that it locks, like this:
with lock.acquire():
queue.append(item)
That style is just asking for trouble; sooner or later you’ll touch the queue without acquiring the lock, and everything will fall apart. Instead, you want to lock the actual data so that you can’t even access the locked thing without acquiring the lock:
with queue.lock() as q:
q.append(item)
P.S. If you deal with something like the original loop without a run() method, you can write a generator to convert a while loop into a for loop:
def run(loop):
while not loop.quit_requested:
yield loop.next_event()
for event in run(loop):
process(event)
Most of the time the difference won’t be significant or worth it, but sometimes this can really help to clarify things, by extracting the loop bookkeeping into one place so that you can do what you were semantically trying to do, processing a stream of events.
P.P.S. Instead of range(999999), use itertools.count() when you want unbounded iteration. Or itertools.repeat(None) if you don’t care about the number—but in that unused number or None see that a for loop is probably not the right tool for what you’ve written: you would be better either shifting back to while loops, or iterating over the data as I’ve demonstrated.