Lesson 5: Infinite loops, modulo, and random numbers Today's lesson collects a few unrelated topics with the goal of giving you some fun and maybe even useful homework problems to work on. ================== while loops ============================== You've written for loops, but I haven't mentioned Python's other kind of loop: the while loop. It looks like this: while condition : do stuff condition is the same sort of thing you might see in an if statement. You could say while x < 3, or while len(s) > 0. You can build more elaborate conditions with and and or: while x < 3 and len(s) > 0 : while (x > 0 and x < 3) or len(s) > 0 : Use parentheses whenever it gets complicated enough that you might get confused about how to evaluate the condition. But most of the time you won't need anything that hairy. There's one more while loop you'll see surprisingly often in Python, the infinite loop: while True : print "This will repeat forever!" (If you try that, Control-C will interrupt the loop.) But using a "while True" doesn't necessarily mean you expect your program to run forever. You can use break to leave the loop. For instance, reading commands from the user: while True : cmd = raw_input("Command? ") if cmd == "quit" : print "Bye" break # if the user typed quit, it's time to leave print "Your command was", cmd =================== Math and Rounding ================== Obviously you can do simple math, like 23 + 52, without any special library. But if you do anything that needs complicated math, like logarithms or cosines, you need the math module. It's straightforward: import math print "log(42) is", math.log(42) It also has some constants, like math.pi and math.e. Read more about it here: http://docs.python.org/library/math.html But there are a couple of math operations I want to talk about that don't require any library. First, conversions: sometimes you make a calculation that might not come out even, but you need an integer. You can truncate -- round down to the next-lowest integer -- with int(): >>> int(45.6) 45 Or you can round to the nearest integer with round(): >>> round(45.6) 46.0 Notice that that's still a floating point number -- it has a decimal point. So if you really need an integer, like if you're going to use it to pick an element in a list, you might need to say int(round(45.6)). You'll know if you need that if you get an error like: TypeError: list indices must be integers, not float ====================== Modulo =========================== A less familiar operation that they don't teach in high school math, comes up in computer programming all the time: the modulo operator. It gives you the remainder when one number is divided by another. It's represented by the % sign in Python (and nearly all other modern programming langagues). >>> 11 % 9 # pronounce this "eleven mod nine" 2 >>> 7 % 3 # "seven mod three" 1 11 divided by 9 is 1 with 2 left over; 7 divided by 3 is 2 with 1 left over. Why is that so useful? Why would you care more about the remainder than about the actual value of the division? For one thing, you can use it to find out whether one number is divisible by another. I have a Python program that shows a ruler, and it uses % to make every 5th tic a little longer, and tics that are multiples of 10 really long. Something like this: for i in range(0, 21) : if i % 10 == 0 : print "-----" elif i % 5 == 0 : print "--" else : print "-" It's handy in lots of other ways too (as you'll see in the homework). The most important thing to remember about modulo is that if you take x % y, you'll always get a number from 0 to y-1. ==================== random ============================== It might seem sort of random to be talking about random numbers this early in a beginner course, but there are so many fun things you can do with random numbers. And Python's random module is really easy to use. You learned in the last lesson how to import modules. To use random numbers, just say import random somewhere near the top of your file. Then when you use anything from random, make sure you call it random.whatever. The two most useful random functions are randint() and choice(). randint() gives you a random number between two boundaries, including the boundarkes: random.randint(0, 1) will give you either a 0 or a 1, random.randint(0, 255) will give you a number from 0 to 255 inclusive. random.choice() is even more useful: give it a list, and it picks a random element of the list. So if you have a list of words like verbs = [ "programmed", "waited", "bubbled", "bounced", "danced the Macarena" ] random.choice(verbs) it will pick one of those verbs. For other stuff it can do: http://docs.python.org/library/random.html That's it for the discussion -- let's do some exercises! ====================== Homework ============================= 1. Suppose you have a list of colors, like colors = [ "red", "orange", "yellow", "green", "blue" ] and you have a bunch of things (say, 20 of them) that you need to color without repeating. How would you use the modulo operator, %, to step through the colors in order, printing out one after another and going back to red after blue? Hint: remember, x % y always gives you a number between 0 and y. What does y have to be so that it always gives you something that could be an index of the list? 2. How would you write a program to choose a random file from a directory full of files? Assume the directory is in some fixed place, like "/usr/share/backgrounds" or "/home/yourname/Backgrounds". Hint: os.listdir(dirname) will give you a list of all the files in a directory. Of course you have to import os first. Why would you want to do this? In my case, I have a big collection of desktop background images, and every time I log in, I have a script that gives me a different wallpaper image that day. (I use hsetroot -center filename to set the wallpaper under openbox; Gnome or KDE users might need a different method.) It's fun to see what image I'll get each day. For a while I did the same thing with my beep tone, so if anything happened to make my computer beep, I might hear a crow or a wolf or a grey whale. But it drove my husband crazy, so I stopped in the name of marital harmony. 3. Make a list of nouns and a list of verbs. Then write a program that makes a random sentence by choosing a random noun and a random verb. You may notice that my verbs are intransitive -- they can be used on their own. So you can say "the cat waited", whereas a noun-verb sentence wouldn't work if you used a transitive verb like "the cat fixed". 4. (Optional) Change your program to add another sentence type or two -- maybe add a list of transitive verbs and make it sometimes choose noun-trans verb-noun sentences, other times just noun-intrans verb sentences. Or add a list of adjectives and add adjectives to your sentences. How would you use random and modulo together to say "sometimes do this type of sentence, other times do this type"? The object here is to have fun writing a program that makes interesting, wacky sentences. If you get ambitious and want to spend some more time, try do this in a loop, taking input from the user each time, and let the user quit by typing q or quit or whatever. You could even ask the user for a noun or verb and then make a sentence using it. By the way, this sort of program is especially fun as a CGI script on the web, like http://itsthisforthat.com/ I wrote a program like that back when I was going to a lot of astronomy star parties. People were posting observing reports that all sounded pretty much alike, and to make fun of them I wrote: http://shallowsky.com/obsreport.cgi (Sadly, it's written in Perl because I hadn't learned Python yet.) The best part is that the guy whose reports I was particularly parodying didn't realize it was a program, and replied "Nice observing report, Akkana, but it seems a little repetitive." Several people told him to try hitting reload a few times. :-)