Chur7U
Chur7U

Reputation: 87

Python decreasing for loop

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

Answers (2)

Arthur Tacca
Arthur Tacca

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

RSHAP
RSHAP

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

Related Questions