Reputation: 87
Imitating an "increasing" C-styled for loop in Python is very simple:
for (int i = A ; i < B ; i += C)
can be easily implemented in Python, Without consuming memory for an array from A to B, using:
for i in range(A, B, C) # (xrange if Python 2.x)
But what about decreasing loops?
How can one imitate C-styled loops such as:
for (int i = A ; i >= B ; i -= C)
Even using reversed(range(A, B, C))
constructs an array in the memory, as reversed
first has to evaluate the whole range
generator in order to yield its values reversed...
Is there any trick for implementing such a for loop in Python, without constructing an array in the memory? Is there an equivalent for range
generator, that yields decreasing numbers?
Upvotes: 4
Views: 10584
Reputation: 9998
Just go ahead and call reversed()
on the result of range()
. It won't build the whole list because the range
object has a __reversed__
method, which the reversed()
function detects and uses. Here's how you can see that it has that method:
>>> dir(range(3))
['__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'count', 'index', 'start', 'step', 'stop']
This is assuming you're using Python 3. In Python 2, range
builds a list in memory regardless of whether you reverse it, although most of the time it makes no performance difference. You can use xrange
, which is like Python 3's range
, and also has a __reversed__
method.
Upvotes: 2
Reputation: 2446
range takes 3 args range(start,stop,step)
. The step arg can be negative to iterate backwards.
arr = range(10) # range generator in python 3
for i in range(len(arr)-1,0,-1):
print(arr[i])
9
8
7
6
5
4
3
2
1
Note that the start is len(arr)-1
because lists are 0-indexed so the max idx is 9 for a list of length 10.
Negative steps don't have to be 1 either:
for i in range(len(arr)-1,0,-3):
print(arr[i])
9
6
3
In answer to your second question, you can set arr to be a countdown from the beginning
arr = range(10,0,-1)
for a in arr: print(a)
10
9
8
7
6
5
4
3
2
1
Upvotes: 4