i have
for i in xrange(repeat):
#does my stuff
time.sleep(10)
BUT, i don't want it to sleep if it's the last run. Meaning, if there's no more iteration, don't sleep
How do I gracefully handle this?
i have
for i in xrange(repeat):
#does my stuff
time.sleep(10)
BUT, i don't want it to sleep if it's the last run. Meaning, if there's no more iteration, don't sleep
How do I gracefully handle this?
case of 1x repetition: doStuff
case of 2x repetition: doStuff, sleep, doStuff
case of 3x repetition: doStuff, sleep, doStuff, sleep, doStuff
...
What you seem to want is to do a bunch of things, then sleep between each of them.
Furthermore, the delay is independent of the nature of the tasks.
Solution 1 -- Sleep if it isn't the last
The easiest way is to special-case the for loop:
for i in range(numTimesToRepeat):
if i>0:
time.sleep(lengthToSleep)
doStuff()
You could also do the following, but it's much less elegant because you repeat doStuff()
:
doStuff()
for i in range(numTimesToRepeat-1):
time.sleep(lengthToSleep)
doStuff()
Solution 2 -- While loop with break
One of the most straightforward ways to solve these issues is to break out of a while loop. It's dirty and somewhat non-functional-programming, but it's very much how a human might naturally think of the problem:
numTimesToRepeat = ...
while True:
doStuff() # we did stuff
numTimesToRepeat -= 1 # repeat one less time because we just did it
if numTimesToRepeat==0: # do we repeat again?
break # no -> done!
else:
time.sleep(lengthToSleep) # yes -> sleep before repeating
While loops are annoying because if you make a programming error, your program will infinite-loop.
Solution 3 -- Detect if last
The above methods do something if it's not the first iteration of the loop. However, "detecting the last iteration of the loop" is how you tried to approach the problem. It is a bit more annoying, but you can do it like this: https://stackoverflow.com/a/6090673/711085 and use it like this:
for i,task,isLast in enumerateLast(tasks):
task()
if not isLast:
time.sleep(lengthToSleep)
Less elegant is to reverse the list and do enumerate()
:
for untilLast,task in reversed(enumerate(reversed(tasks))):
task()
if untilLast>0:
time.sleep(lengthToSleep)
(very small irrelevant minutiae: do note that in the reversed(enumerate(reversed(iterable)))
case, if tasks were a generator, it would generate every single task to do, enumerate them in reverse order, then do them: this can cause lag, and also prevents you from creating an infinite task generator)
Task abstraction
No matter which way you do it, you may wish to abstract the concept of having tasks by creating callbacks, into which you insert a delay between each, sort of like a ''.join
.
def callAndWaitBetween(tasks):
for ..task.. in enumerate?(tasks):
#... some solution to this problem...
task()
For reference, if the delay depended on the tasks, then your tasks should return how long to wait.
If all you do is sleeping, you can do
for i in range(repeat)[:-1]:
time.sleep(10)
But if you actually need to perform some type of action, then:
sleep = [lambda: time.sleep(20) for i in range(repeat)[:-1]] + [lambda: None]
for i in xrange(repeat):
# do stuff
sleep.pop(0)()
If you really have a lot of iteration, use itertools
to create a generator instead of a list for sleep
.
A while loop might work
while repeat > 0:
#do stuff
if repeat > 1:
time.sleep(10)
repeat -= 1
Just set repeat directly to the number of times the loops is to be repeated instead of using xrange.