问题
Why does this not create an infinite loop?
a=5
for i in range(1,a):
print(i)
a=a+1
or this
for i in range(1,4):
print(i)
i=i-1
or this
for i in range(1,4):
print(i)
i=1
Is there any way we can create infinite loops using a for
loop? I know there is the while
loop for that but I was just curious.
回答1:
range is a class, and using in like e.g. range(1, a)
creates an object of that class. This object is created only once, it is not recreated every iteration of the loop. That's the reason the first example will not result in an infinite loop.
The other two loops are not infinite because, unlike the range
object, the loop variable i
is recreated (or rather reinitialized) each iteration. The values you assign to i
inside the loop will be overwritten as the loop iterates.
回答2:
Consider a for
loop:
for item in iterable:
print(item)
The idea is that as long as iterable
is unchanged, we will loop through each and every item
inside iterable
once. For example,
for item in [3, 2, 1, 666]:
print(item)
will output 3 2 1 666
. In particular, we find that range(1, 4)
is a easy way to represent an iterable [1, 2, 3]
. Thus,
for i in range(1, 4):
print(i)
will output 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
is reevaluated every loop, before executing the print
and i=i-1
statements within the body of the loop.
Example 3
for i in range(1,4):
print(i)
i=1
Just like Example 2, i
is reevaluated every loop.
回答3:
You can't, in this case, update the iterator that your for
loop is looping over.
The range
in for i in range(a):
is actually a function - it takes a value, a, and returns an object that contains the values that it will loop through. Once you've built that object you can change the input variable as much as you'd like, and that object won't change.
Imagine if we made our own similar function called my_range
that generates a list (whereas the built in range
function generates a 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, like so:
a = 4
for i in my_range(a):
print(i)
a += 1
It'd be obvious that we can't update the list object that we're looping over by changing a
, because the list that we're looping over has already been made, and isn't being remade on every loop.
Can you make an infinite loop in python? Yes, just add a new entry to the object that you're looping through, e.g.:
my_list = [0]
for i in my_list:
print(i)
my_list.append(i+1)
Now we're updating the object that we're looping over.
回答4:
Because a range is either a list (Python2) or a range
object both of which are finite. That range is created once before the loop starts. Your loop variable is assigned the next element of the range at the beginning of each iteration, regardless of what you assign it later in the loop body. You need an infinite iterator for an infinite for loop, e.g. itertools.cycle
:
from itertools import cycle
for x in cycle(range(5)):
# endless
回答5:
for
loops and the range(..)
object
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).
Furthermore the range object is constructed once, before the for
loop. The range(..)
object, does not know which variables have been used to construct it. Once constructed, the range is fixed.
It sees range(..)
as an iterable object, and each iteration, it takes the next item the iterable yields. So whether you set the variable or not in the for
loop, has no effect for the next iteration.
In python-2.x, range(..)
is not a specific object, but a call to construct a list. So if you call range(10)
(without the for
loop), you get [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
.
Why it does not work?
So then why does the examples do not work?
a=5
for i in range(1,a):
print(i)
a=a+1
Here we construct range(..)
once. After that, the variables based on which it was constructed can change, since the range(..)
object does change anymore. Incrementing a
thus will not mean the range
object will get larger.
for i in range(1,4):
print(i)
i=i-1
The for
loop each time takes the next item of the iterable. So if we first have collected 1
from the range
loop, the next iteration, we collect 2
. This is regardless what the value of i
is.
for i in range(1,4):
print(i)
i=1
For the very same reason: for
does not take into account the previous value of i
. It only fetches the next item the iterable (here range(..)
yields). Since range(..)
is fixed, it will simply feed the for
loop the next item.
Emulating an infinite loop
So we need to construct an iterable that keeps yielding elements. A way to do this is itertools.count
:
from itertools import count
for i in count():
# ...
pass
Or in case you are not interested in any value, we can use repeat
as well:
from itertools import repeat
for _ in repeat(None):
# ...
pass
回答6:
range
copies the parameters given to it for internal use. So changes to those afterwards have no effect. Same as with the loop variable, which is only created from the internal values every time.
That's different though if you use a mutable object like a list
to iterate over:
a = [1,2,3]
for i in a:
a.append(i)
This loop will indeed run infinitely.
来源:https://stackoverflow.com/questions/48206443/infinite-loops-using-for-in-python