Reputation: 91
I'm just wondering what the most "pythonic" way to increment a varible x
all the way from 0 to 100, then when x
reaches 100, deincrement back to 0 then back again to 100 in a loop over and over...
Something like this:
x = 0
while True:
if x < 100:
x += 1
elif x == 100:
x -= 1
NB: Above code is broken, hence my question. :)
What is the simplest way to do this - not necessarily the shortest code, not looking for a one liner, just a really nice bit of code.
Upvotes: 0
Views: 2493
Reputation: 884
well since no one else is doing it, why not some generator fun!
def lazy_forever_and_ever(hi, lo, start=0, step=1):
x = start
vals = {hi: lo, lo: hi}
target=lo
while True:
if x == target:
target = vals[target]
if x >= target:
yield x
x -= step
elif x <= target:
yield x
x += step
if __name__ == '__main__':
_4eva = lazy_forever_and_ever(0, 10, 0, 1)
print([next(_4eva) for _ in range(20)])
# output
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
Upvotes: 0
Reputation: 185
Well, your current solution won't exactly work - you'll deincrement back to 99, then cycle between 99 and 100.
The simplest might be to add a direction
flag, for example:
x = 0
isIncreasing = True
while True:
if isIncreasing = True:
x += 1
if x == 100:
isIncreasing = False
else:
x -= 1
if x == 0:
isIncreasing = True
I'm there's a more "one line" way to do this with itertools (see above posts), but this would be the most "direct" solution in your current case. Of course, what you're really looking for is a generator
.
Upvotes: 0
Reputation: 477210
First of all your code does not work: it will count to 100, and then swap between 99 and 100. So: 1,2,3,..,99,100,99,100,99,...
Actually the most Pythonic way is probably not to increment/decrement at all, but use two range
s:
while True:
for x in range(101):
pass
#do something with x
for x in range(99,0,-1):
pass
#do something with x
Or construct an infinite generator with itertools:
generator = itertools.cycle(itertools.chain(range(101),range(99,0,-1)))
and then you can use it as:
for x in generator:
pass
#do something with x
Fr instance (I here use 2
because it makes the answer more compact):
for x in itertools.cycle(itertools.chain(range(3),range(1,0,-1))):
print(x)
will produce:
0
1
2
1
0
1
2
1
0
the loop will be repeated infinitely.
A way to fix your code however would be to add a direction, but this is probably not very Pythonic:
x = 0
dr = True
while True:
if dr:
x += 1
if x >= 100:
dr = False
else:
x -= 1
if x <= 0:
dr = True
#do something with x
Upvotes: 2
Reputation: 603
I find one-liners simple... so what about this:
Python 2:
from itertools import *
ups_and_downs = cycle(chain(xrange(100), xrange(100, 0, -1)))
Python 3:
from itertools import *
ups_and_downs = cycle(chain(range(100), range(100, 0, -1)))
(edited to remove the one-off error)
Upvotes: 3
Reputation: 1337
How about trying this?
x = 0
inc = 1
while True:
# do your job here
if x == 0:
inc = 1
elif x == 100:
inc = -1
x += inc
Upvotes: 1
Reputation: 184280
There's nothing wrong with using two loops!
while True:
for x in range(100):
do_something(x)
for x in range(98, 0, -1):
do_something(x)
Or you could use a variable to keep track of which direction you're going:
delta = 1
x = 0
while True:
do_something(x)
x += delta
if x < 1 or x > 99:
delta = -delta
Upvotes: 1