Infinite loops using 'for' in Python

Why doesn't this create an endless loop?

a=5 for i in range(1,a): print(i) a=a+1 

or

 for i in range(1,4): print(i) i=i-1 

or

 for i in range(1,4): print(i) i=1 

Is it possible to create infinite loops with a for loop? I know there is a while for this, but I was just curious.

+5
source share
6 answers

range is a class and uses it, as, for example, range(1, a) creates an object of this class. This object is created only once; it is not recreated at each iteration of the loop. The reason is that the first example will not lead to an infinite loop.

The other two loops are not infinite, because, unlike the range object, the loop variable i recreated (or, rather, reinitialized) of each iteration. The values ​​you assign to i inside the loop will be overwritten as the loop repeats.

+5
source

Consider the for loop:

 for item in iterable: print(item) 

The idea is that until iterable changes, we will scroll through each item inside iterable once. For instance,

 for item in [3, 2, 1, 666]: print(item) 

outputs 3 2 1 666 . In particular, we find that range(1, 4) is a simple way to represent iterable [1, 2, 3] . In this way,

 for i in range(1, 4): print(i) 

outputs 1 2 3 .


Example 1

 a=5 for i in range(1,a): print(i) a=a+1 

In this case, range(1,a) is evaluated once when the loop begins.

Example 2

 for i in range(1,4): print(i) i=i-1 

In this case, i reevaluates each cycle before executing the print and i=i-1 statements inside the body of the cycle.

Example 3

 for i in range(1,4): print(i) i=1 

Just as Example 2 , i reevaluates each cycle.

+3
source

In this case, you cannot update the iterator so that the for loop loops.


range in for i in range(a): actually a function - it takes a value, a and returns an object containing the values ​​that it will scroll through. After you have built this object, you can change the input variable as much as you want, and this object will not change.

Imagine if we created our own similar function called my_range , which generates a list (whereas the built-in range function generates range ):

 def my_range(end): my_list = [] for i in range(end): my_list.append(i) return my_list 

Now, if we were to use our new function, for example:

 a = 4 for i in my_range(a): print(i) a += 1 

It would be obvious that we cannot update the list object that we are looping by changing a , because the list we are looping is already done and does not go over every cycle.


Can you create an infinite loop in python? Yes, just add a new entry to the object you are looping, for example:

 my_list = [0] for i in my_list: print(i) my_list.append(i+1) 

Now we are updating the object that we are looping.

+3
source

for and range(..) object range(..)

If you write for i in range(..): Python does not translate this into something like for(int i = 0; i < n; i++) (in the C programming language family).

In addition, the range object is constructed once before the for loop. The range(..) object does not know which variables were used to create it. After building, the range is fixed.

It sees range(..) as an iterable object, and each iteration takes the next element, which has an iterative output. So, regardless of whether the variable is set or not in the for loop, the effect does not work for the next iteration.

In python-2.x , range(..) not a specific object, but a call to build a list. Therefore, if you call range(10) (without a for loop), you get [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] .

Why is this not working?

So why the examples do not work?

 a=5 for i in range(1,a): print(i) a=a+1 

Here we build range(..) once. After that, the variables on the basis of which it was constructed can change, since the range(..) object will change more. Thus, incrementing a does not mean that the range object will become larger.

 for i in range(1,4): print(i) i=i-1 

The for loop takes the next iteration element each time. Therefore, if we first collected 1 from the range loop, the next iteration, we collect 2 . This is independent of the value of i .

 for i in range(1,4): print(i) i=1 

For the same reason: for does not take into account the previous value of i . It only extracts the next element iterable (here range(..) gives). Since range(..) fixed, it simply passes the for loop to the next element.

Endless loop emulation

So, we need to build iterability that preserves inferior elements. The way to do this is itertools.count :

 from itertools import count for i in count(): # ... pass 

Or, if you are not interested in any value, we can use repeat :

 from itertools import repeat for _ in repeat(None): # ... pass 
+1
source

Because a range is either a list (Python2) or a range object, both of which are finite. This range is created once before the start of the cycle. Your loop variable is assigned the next range element at the beginning of each iteration, regardless of what you assigned later in the loop body. You need an infinite iterator for an infinite loop loop, for example. itertools.cycle :

 from itertools import cycle for x in cycle(range(5)): # endless 
+1
source

range copies the parameters provided to it for internal use. Thus, the changes after this are not affected. Same as with a loop variable that is created only from internal values ​​each time.

This is different than if you use a mutable object like list to iterate:

 a = [1,2,3] for i in a: a.append(i) 

This cycle will work forever.

+1
source

Source: https://habr.com/ru/post/1274630/


All Articles