Thanks for the reply.
Why does 3 cause an infinite loop?
Thanks for the reply.
Why does 3 cause an infinite loop?
Three is less than or equal to five, so the loop condition is true, and the loop body is entered. Then, there is nothing inside the body of the loop that ever updates the value to anything other than three, so every time the loop body finishes and the loop condition is evaluated again, it will still always be true.
Edit: Just to be clear, in my example, this is the entire loop:
current_number = 3
while current_number <= 5:
print(current_number)
print("done")
I’ve added a print("done")
to hopefully make it clear that there is only one line inside the loop, and that line does not update current_number
. The print("done")
will never be reached.
Ah I see. Thanks.
Well this, I can’t possibly understand since I didn’t learn any of it yet lol.
You’re overthinking this.
print()
does nothing to the value or the variable. It just displays
the current value. What gets displays depends on where the print()
is:
before or after the increment.
Think of it like one of those stupid card based magic tricks: you, the
mark, pick a card and show it to the audience and not to the magician -
it’s a nice clean card. This is the first print()
. The magician asks
you to scribble on the card so that you can rwecognise it later, and you
show it to the audience so that they see what you’ve scribbled. This is
the second print()
. Now you insert the card at a random place in the
deck, the magician fails to find it and is laughed off the stage.
The code runs exactly the same way with or without the print()
s; all
their presence does is show the value to the audience at that point in
the loop.
Speaking of being on the right track, let’s give this a shot. Let’s reconsider the original diagram with a slight modification:
Here I have added two cars, one blue and one green. Each car is responsible for delivering their respective cargo around the loop. In the diagram, it shows the load
that each car is responsible for. As before, create two columns, and write down the values during each iteration that is valid. By valid, I mean when the value of the variable current_number
is in the diamond above and being compared satisfying the conditional statement less than or equal to 5
.
Now imagine that you’re pushing each car slowly around the loop as highlighted by the arrows. The green car is being pushed by your left hand and the blue car is being pushed by your right hand. Now, as stated before, both cars ONLY re-enter the loop if the current_number
is less than or equal to 5
. If the condition is not satisfied, the loop is exited immediately.
Give that a shot. Maybe interactive participation will aid in the understanding.
Thanks for the analogy. A little confusing, but I think I understand what’s going on in the loops now.
After searching online I think I understand it now. Thanks for this post.
After about five days I think I finally understand this now. I still think it’s odd, but I think I get it. Hopefully I won’t run into it often. Thank you everybody for helping me. I appreciate this community’s effort.
Now that I think I understand this, I want to get back to this post. Is there ever a reason why I’d need to use a while loop instead of a for loop for this kind of iteration? Can a for loop do anything a while loop can do, and better?
I can finally move on to the next part of this chapter.
well, if you take my example above the async thread is just a dumb worker and does not know for how long (but happy )
Any for
loop can be rewritten as a while
loop that manages the iterator explicitly; I think it’s self-evident that for
loops provide a more readable alternative to doing that. You can rewrite the for
loop
for i in x:
do_something()
using the following while
loop:
x_iter = iter(x)
while True:
try:
i = next(x_iter)
except StopIteration:
break
do_something()
del x_iter
It gets a little more complicated when you need to accommodate continue
, break
, and an else
clause on the for
loop.
On the other hand, rewriting any while
loop as a for
loop would require writing an appropriate iterator to capture what the while
loop is doing. Sometimes that may be straightforward, but other times it might require far more work than the simple boilerplate code needed to turn a for
into a while
.
Just FYI, you can reply to many people in one post by simply selecting the relevant text you want to reply to on each post and clicking the Quote
button that pops up. That avoids you having to make a half dozen posts, is much clearer what you’re replying to, and only pings people following the thread with one notification rather than several
Good question; the answer depends on what you mean by “this kind of iteration”. In summary, if you have or can easily create an iterable/iterator (such as a collection, file, range, generator, itertools iterator, etc.), and you want to iterate exactly once through each item in the iterable/iterator in a fixed order (either the order of the iterable, or something it can easily be reordered to a priori), then you want a for
loop. That covers a large majority of cases in most Python use cases, but certainly not all.
Otherwise, if either of those conditions can’t be easily met, then you likely want a while
loop instead. For example, the most common case of the former is almost any infinite loop, e.g. an asyncio event loop, GUI event loop, handler for reading incoming network connections, etc; or, where you want to repeat some action until some condition is reached. In terms of the latter, this would include cases where you want to skip around in your data structure, iterate an arbitrary number of times on items, go back to previous items, or most other cases where iteration happens in a difficult to predictable, dynamic or otherwise not easily modeled a priori fashion—for example, a binary search.
Or, at least for a while True
loop, you could just cop out and do the equivalent (except you get a iteration counter “for free” if you want it):
for __ in itertools.count():
...
And to handle while
loops with conditions:
for __ in itertools.count():
if not <condition>:
break
...
The latter case’s behavior would differ in one (rather uncommon) respect: if there was a (rarely-used) else
block after the loop, it would not fire if <condition>
became false (since the loop was broken out of manually), whereas it would in the equivalent while
loop. Of course, you could replicate that behavior too by e.g. setting some variable normal_exit
to True
immediately before the break
and changing the else
to an if normal_exit
.
You can often rewrite
while condition:
to
for _ in iter(lambda: bool(condition), False):
(The bool()
call might not be necessary.)
For a simple loop, I prefer for loop as it feels natural and easy to me. Consider your example in the 1st post, it is simpler in for loop as follows:
for i in range(5):
print(i+1)
IMHO, while loop is just a repeated if condition. You need it only when you want to check multiple conditions.
For instance,
current_number = 1
while current_number <= 5 and current_number * current_number <= 20:
print(current_number)
current_number += 1
You will get 1, 2, 3, 4.
Or you want infinite loop forever
current_number = 1
while True:
print(current_number)
current_number += 1
Actually, as I and the others who already replied to this have described in detail, the use cases in which one should use a for
loop vs. a while
loop do not really have to do with the “simplicity” of the loop (after all, what could be “simpler” than while True
?), nor the reasons with one particular developer’s personal opinions; but rather whether the use case involves a predetermined iteration over an iterable, and whether the desired task matches the purpose for which each construct exists.
The user’s question you quoted was itself a direct reply to a post making the same point, including a nearly identical example, so I’m not entirely sure what purpose repeating it here serves, sorry?
To note, ISTM that it makes more sense to specify the actual desired endpoints of the range from the start (as my example did)…
for i in range(1, 6):
print(i)
…instead of iterating over a different range and only adjusting it later inside the print call.
Indeed; this is not merely just your own (humble or otherwise) personal opinion , but rather the objective behavior of the logic, as described and demonstrated by our previous posts (minus the
else
block, and possible pathological cases).
I don’t understand what you’re trying to claim here about only needing it when checking “multiple conditions”, sorry. I’m not sure how the number of conditions one is checking has any relationship whatever with whether you’d want to use a while
loop (as opposed to the considerations we’ve mentioned above)?
It is quite common to use while True
when one needs an infinite loop, but as we’ve stated, ultimately the question of while
vs for
comes down to whether you’re iterating in a predetermined order over an iterable. In this case, given you are (the set of integers 1…infinity), it is considerably simpler and more idiomatic to use a for loop as we’ve illustrated above, i.e.:
for n in itertools.count(start=1):
print(n)
I didn’t know I could do that. Thanks.
I’ll come back to the rest of your reply when I understand this stuff more. Appreciate it and everyone else’s replies.