Loops
Last time we learned about
input and a little about
if statements. Today, let's talk about
loops. A
loop is a
block of code that runs a certain number of times (possibly not at all) depending on a
condition or some other mechanism.
Before we get started, create a new folder in the python directory we set up in Lesson 3, and call this new folder "Lesson 6"; then open up your text editor and create a new file ("lesson6.py").
[pic]
The while Loop
The
while statement begins a loop. It looks a whole lot like an
if statement, but it functions quite differently. The loop only starts if the beginning
condition is met, and the block runs to the end. Once the loop reaches the end of its block, the condition is tested again. If the condition is met again, the loop repeats and continues to do so until the condition is False.
How is this useful? Well, let's think back to the previous lesson and the name entry we did. Let's do that again, only this time, let's make it so you cannot enter an empty string for a name. The program will keep asking until you enter a non-empty string.
Let's begin. Type this in your document:
print "What is your name?"
name = raw_input("Enter your name>")
This will get the name from the user. Now let's write our
while loop to make sure the name is not empty.
while(name==""):
print "You cannot enter an empty name"
name = raw_input("Enter your name>")
Now let's try running what we've got so far. Open up your console and navigate to your "Lesson 6" folder. Now run your program
python lesson6.py
Ok we've got our prompt. Now hit return or Enter a few times.
See? It keeps running that code over and over, and will run it forever until the condition is False. That means if we enter something,
name will no longer be the empty string, and the loop will
terminate.
It worked! We exited the loop, and the program terminated.
Now let's try something even more useful. Say you want the user to enter an
integer, but you want to be sure that they enter a number and not just letters or symbols (because if you use the
int() function on a string that cannot be turned into an
integer the program will
crash).
Type this into your program
print
print "Now enter an integer."
strNum = raw_input("integer>")
Ok, now how do we test if
strNum is an integer? Turns out there's a string method called
isdigit() that will get us pretty close to what we want. It's not perfect, but it will do for purposes of this exercise. Type this into your program
while(not strNum.isdigit()):
print "You must enter a number"
strNum = raw_input("integer>")
Wait! What's that
not doing there? If we put
not put it before a
boolean,
we get the opposite of the value (True instead of False, and vice versa). In this case, we only want to run the loop if
strNum is
not an integer.
Now after all that, type this
num = int(strNum)
This should work for most integers (if not all). Now let's get some output going.
print "Ok, " + name
print "The square of your number is " + str(num * num)
That will
the print the name the user entered, plus the square of the number entered.
Another useful thing you can do with loops is do operations for sequences of numbers. For this example, let's create a new document; save it as a different name (like "lesson6-2.py").
[pic]
Ok, let's start by creating a variable to hold our number. A common programming standard for situations like this is to use a variable called
i.
i = 0
This is going to be our
counter. Let's say we want to add up all the numbers from 1 to 100. Let's create another variable to hold the sum.
sum = 0
Ok now we need our loop. The condition for the loop is that i <= 100, so let's start there. Then we'll add a the value of
i to
sum.
while(i <= 100):
sum = sum + i
print sum
Remember that since "print sum" is not indented that it will run after the loop finishes. If we had indented it, it would print the value of
sum each time through the loop.
Now let's run it.
Oops! What's happening? We didn't ask for input? Why isn't anything happening? That's because we forgot one tiny detail. See the condition? Each time through the loop,
i is always 0, so we end up looping forever! We need to change our program a bit.
But first use an
interrupt to exit your program. Hit ctrl+C.
We exited our program. Ok so now how do we fix the loop? Just change the loop to be this:
while(i <= 100):
sum = sum + i
i = i + 1
Now let's try to run it.
It worked! Now for a few optimizations. For instance, when
i is 0, we're adding 0 to 0 (in
sum). We really don't need that (not that it matters too much as far as performance goes). So let's just change
i = 1
That's better. Now for the assignment with addition. There are special assignment operators for most mathematical operations that tell Python to, for example, add a number to a variable and store the result back in that variable. For instance, on the line
sum = sum + i
we can instead say
sum += i
And we can do the same thing for
i.
i += 1
There! Our program is much more succinct.
Now let's move on to another kind of loop.
The for Loop
In Python, the
for loop is your friend. It helps you
iterate (repeat a process on) through
collections like lists and so forth. Remember back in
Lesson 4 when we first learned about lists and we wrote a program that printed items in a list to the screen one by one using square brackets ([])? That didn't seem very useful, and it's not. The better way is to use a
for loop.
Open a new file in your text editor and save it (lesson6-3.py).
First we'll create a list of
strings. Let's use names.
nameList = ["Bob", "Sue", "Mary", "Joe"]
Now let's say that we want to print each of those names to the console. We could do something like this:
print nameList[0]
print nameList[1]
print nameList[2]
print nameList[3]
It works, but it's a lot of duplicate code, and what if we didn't know how long the list was when we were writing the program? With the
for loop, the list can be any size at all. Here's what the for loop looks like:
for thisName in nameList:
Ok, here's what it means. We want to create a loop which runs once for each item in
nameList. Each time through the loop, the item from the list we are using will be stored in the variable
thisName. (We know that these will all be strings.)
Now for the useful part.
print thisName
So the total loop looks like this:
for thisName in nameList:
print thisName
Now let's run it and see what we get.
It worked! It went through each item in the list (in order), and we told it to print that item to the console.
There's a way we can do the same thing with a
while loop. First let's create a line.
print "-" * 80
Now let's create a variable that will hold the
index of the item we are working on.
i = 0
Now we'll create our loop.
while i < len(nameList):
What does this mean? Well, let's finish the rest of the loop, and then I'll explain. (Remember to indent)
print nameList[i]
i += 1
All right. See how in that last line we are adding 1 to i and then reassigning it? (We could have written it "i = i + 1") The value in
i will always increase by 1 each time through the loop. The
condition of this
while loop will remove us from the loop when
i is not less than the length of the list. (Since we're adding 1 each time, this will happen when i equals the length of the list (4).)
So the values being tested for
i will be 0, 1, 2, 3, and 4. When
i equals 4, it is no longer less than the length of the list, and the loop doesn't run anymore.
This is what makes
zero-based lists so advantageous. The last item in the list will always be the length of the list minus 1. Therefore, loops through a zero-based lists always check to see that the index is less than (<) the length. If this were
one-based, we would have to check to see if
i was less than or equal to the length (<=) because the last item index and the length of the list would be the same.
Remembering that one thing will help you out a lot in programming. But see how in this case the
for loop is much simpler? (There will be times when you will want to use a while loop, but we won't get into that now.)
Okay, now let's try it
Ta-da! Now, if we really wanted to emulate the
for loop, we would have done something like this:
i = 0
while i < len(nameList):
thisName = nameList[i]
print thisName
i += 1
As far as our program is concerned, these two loops do the exact same thing—they both go through each item in the list and assign the item to the variable
thisName.
Let's Put It All Together
Ok now, let's write a program that incorporates everything we covered in this lesson. Create a new file and save it (lesson6-4.py).
We are going to make a program that lets the user enter in as many words as he wants. When that's done, we'll change each word to uppercase and then print them to the screen.
First, we'll create the list to hold the words. (Okay, they don't necessarily have to be words; they can be any string, but for purposes of this program, we'll call them words.)
wordList = []
Now let's make a variable to hold the user's input.
currentWord = ""
Let's do something to spice things up a bit. Each time the user enters a word, let's give them a prompt that tells them what number of word they are entering (eg "word 3:"). Let's create a variable to hold that number.
wordNum = 1
Why are we starting at 1? In user interface design, you generally don't start at 0. Think of a spreadsheet program (like Microsoft Excel); the numbering starts at 1—not 0. Thus we will start at one, though we know the actual index will be one less than whatever the prompt says.
Now let's start our loop.
while currentWord != "":
This will kick us out of the loop when the user enters an
empty string (in other words, the user just hits return or Enter). But we have a problem now: the first time through the loop,
currentWord is already an empty string. How can we fix this? How about we put an input statement before the loop. Change the line
currentWord = ""
to
currentWord = raw_input("word 1: ")
By doing that, our wordNum will be off by 1 when we start the loop, so let's change it to be
wordNum = 2
There we go. See how thinking through things helps? You don't have to get things right the first time; if something doesn't work, or you think of a better way, change it.
Ok now for the body of the loop. First let's add our word to the list (remember to indent)
wordList.append(currentWord)
We know for certain that we're not adding an
empty string, because we just tested for that as the condition for the loop. If the user hits return or Enter on the first word, the loop won't run even once.
Now let's create the string for our prompt
prompt = "word " + str(wordNum) + ": "
I hope that's pretty self-explanatory. (Remember that the str() function is necessary so we can convert the integer to a string before
concatenation.)
Now for the input using the prompt we just made.
currentWord = raw_input(prompt)
And last but not least, we want to
increment (add one to)
wordNum.
wordNum += 1
Without that, our prompt would be "word 2: " each time through the loop.
Now that we've got our word entering loop, let's create a loop to display the uppercase words. We can do this in one of two ways: we can change them all to uppercase, store them, and then display them; or we can change them to uppercase at the same time as we display them.
The second method is the easiest, since we don't care to have the uppercase words when we're done:
for word in wordList:
print word.upper()
Remember that
upper() (like all string functions) only
returns the uppercase string; it doesn't change the original string.
Incidentally, we could have also stored each word as an uppercase string at the time the user entered it by doing this:
wordList.append(currentWord.upper())
Which way is the best way? That depends on what you want. If you don't care to have the original input, convert it when the user enters it. If you don't care to store the uppercase strings, convert it when you print it. If you want to keep both, do what we're about to do next.
First, let's make a new list for the uppercaseStrings.
uppercaseWords = []
Now let's go through our list, convert them, and add them to the new list.
for word in wordList:
uppercaseWords.append(word.upper())
Now to print them.
for word in uppercaseWords:
print word
There we go. Now let's run it.
Voila! It works.
Review
- Loops are blocks of code that can run more than once.
- The while loop runs until its condition evaluates to True.
- Code that is part of the loop is indented.
- A counter is an integer that is incremented each time through the loop so that you can keep track of how many times the loop has run.
- The for loop is used to loop through items in a collection (like a list, for example).
Well that's it for now. See you next time.