Reputation: 435
I'm about 2 weeks deep in my study of Python as an introductory language. I've hit a point in Zed's "Learn Python the Hard Way" where he suggests:
Use a while-loop only to loop forever, and that means probably never. This only applies to Python, other languages are different.
I've googled all over this, referenced everything I can, but I can't find any reason in the world why this would be a convention in Python. What makes it different?
When I gave up programming 10 years ago, I was working in VB and would regularly be told to get rid of my For loops and use While loops instead. I was a hack (as I am today, though I wrote a LOT of code back then), so I just did what I was told without questioning it. Well, now I'm questioning it. Is this a speed issue? Is it just to avoid escape-less infinites?
Upvotes: 28
Views: 14141
Reputation: 131667
>>> counter = 0
>>> while counter < 5:
print(counter)
counter += 1
0
1
2
3
4
>>> for x in range(5):
print x
0
1
2
3
4
See for yourself, which one do you prefer?
When an easier to understand and easier to read code works, that is the Python-ic
way.
Upvotes: 3
Reputation: 63729
The general issue with while loops is that it is easy to overlook, or somehow skip the statement where the loop variable gets incremented. Even a C for-loop can have this problem - you can write for(int x=0; x<10;)
, although it is unlikely. But a Python for loop has no such problem, since it takes care of advancing the iterator for you. On the other hand, a while loop forces you to implement a never fail increment.
s = "ABCDEF"
i = 0
while (i < len(s)):
if s[i] in "AEIOU":
print s[i], 'is a vowel'
# oops, this is one level too deep
i += 1
is an infinite loop as soon as you hit the first non-vowel.
Upvotes: 6
Reputation: 3671
Python follows the philosophy of
There should be one-- and preferably only one --obvious way to do it.
(see https://www.python.org/dev/peps/pep-0020/ for details).
And in most cases there is a better way to do iterations in Python than using a while loop.
Additionally at least CPython optimizes other kinds of loops and iterations (I consider map and list comprehensions as kinds of iteration) better than while loops.
Example: https://www.python.org/doc/essays/list2str
Use intrinsic operations. An implied loop in map() is faster than an explicit for loop; a while loop with an explicit loop counter is even slower.
I have no explanation why you were told to use while loops instead of for loops in VB - I think it normally leads neither to better readable nor to faster code there.
Upvotes: 9
Reputation: 172249
Why avoid while loops? For training purposes. I quote from the book:
Never be a slave to the rules in real life. For training purposes you need to follow these rules to make your mind strong, but in real life sometimes these rules are just stupid. If you think a rule is stupid, try not using it.
The fact is that some of these rules are stupid all the time, in real life. Avoiding while loops is one. His rule for for loops is that you use them when there is a list (or tuple or generator) of elements to iterate over or a fixed number of iterations. This is correct. When there is not, and you instead have a certain state or condition you want to reach, you use while loops. Only using them when you have an infinite loop (like event handlers) is a stupid rule. But newbies tend to use them too often, maybe that's why he has the rule there.
Upvotes: 0
Reputation: 22979
I think that using infinite loop is conceptually wrong, because an algorithm is, by its definition, composed by a finite numbers of instructions (wikipedia):
In mathematics, computer science, and related subjects, an algorithm [...] is an effective method for solving a problem expressed as a finite sequence of steps.
In my opinion is better to find another solution than the infinite loop whenever possible, and this applies to every programming language past, present and future.
Upvotes: 1
Reputation: 4891
The for loop is best for looping through a collection. I mostly think of the for loop as a "definite loop." Using a for loop for a collection prevents errors arising from attempting to use indices that are out of bounds or from accidentally using negative indices. Unless you are in a special situation, use a for loop for traversing a collection.
The while loop is most useful for situations where you may have to repeat an action an indefinite number of times. It is the "indefinite loop". The example shown above for calculating a gcd is a prime example of where to use a while loop. You must bear in mind that the predicate in the while must change, or you could get stuck in an infinite loop.
If at all possible, avoid using break to get out of a loop.
Upvotes: 2
Reputation: 198587
Let me share a secret with you: Nine times out of ten with python, the answer is just "use common sense". It's not a terribly tricky language (aside from some notable gotchas). In this case, I'd consider Zed's rule of thumb superfluous because it's almost always common sense to know what kind of loop to use.
That said, if I run into a situation that requires iteration and I have a choice, I prefer the following (from greatest to least preference):
Comprehensions are simple, but it's surprising how many times you can make a for loop into one if you put thought into it. But generally, I'd say that about 90% of all iteration I'll do is with a list comprehension or a for loop.
Upvotes: 3
Reputation: 19037
This is an idiom I use frequently:
done = False
while not done:
done = DoSomeStuffAndReturnTrueIfAllDone()
# wait a while before polling again for more work
time.sleep(5)
I could pull this out into a generator, sure, but I don't see that as a win. Are there other pythonic ways to do this?
Edited to clarify that I'm periodically polling for work.
Upvotes: 2
Reputation: 36203
It's because in the typical situation where you want to iterate, python can handle it for you. For example:
>>> mylist = [1,2,3,4,5,6,7]
>>> for item in mylist:
... print item
...
1
2
3
4
5
6
7
Similar example with a dictionary:
>>> mydict = {1:'a', 2:'b', 3:'c', 4:'d'}
>>> for key in mydict:
... print "%d->%s" % (key, mydict[key])
...
1->a
2->b
3->c
4->d
Using a while
loop just isn't necessary in a lot of common usage scenarios (and is not "pythonic").
Here's one comparison from a mailing list post that I though was a good illustration, too:
> 2. I know Perl is different, but there's just no equivalent of while
>($line = <A_FILE>) { }
?Python's 'for' loop has built-in knowledge about "iterable" objects, and that includes files. Try using:
for line in file: ...
which should do the trick.
Upvotes: 11
Reputation: 65854
The advice seems poor to me. When you're iterating over some kind of collection, it is usually better to use one of Python's iteration tools, but that doesn't mean that while
is always wrong. There are lots of cases where you're not iterating over any kind of collection.
For example:
def gcd(m, n):
"Return the greatest common divisor of m and n."
while n != 0:
m, n = n, m % n
return m
You could change this to:
def gcd(m, n):
"Return the greatest common divisor of m and n."
while True:
if n == 0:
return m
m, n = n, m % n
but is that really an improvement? I think not.
Upvotes: 27
Reputation: 275917
Also there are list comprehensions e.g.:
>>> vec = [2, 4, 6]
>>> [3*x for x in vec]
[6, 12, 18]
Upvotes: 2
Reputation: 3066
It is not a speed issue, and it is what it is, a suggestion.
I think the intention is to make the code more explicit and easier to read. If you can write it without a while loop in python, it probably looks cleaner and is easier to understand.
Upvotes: 4
Reputation: 385980
A while loop is a tool, nothing more. To use it or not use it is a matter of whether it's the right tool for the job, nothing more. You are right to question the advice, it's silly.
That being said, there are constructs in python that obviate the need for while loops some of the time. For example, list comprehensions do things one might ordinarily do with a while or for loop.
Use the right tool for the job, don't try to memorize and stick to a bunch of rules. The goal is to write code that a) works and b) is clear.
Upvotes: 4