Python: ad infinitum

In Seth’s post on dice rolling, he briefly mentioned something called a “while loop”. It has the basic structure

while (this is true):
    (do this)

Note: Courier font or italics show code. WordPress is douchey about font-changing, so it’s easier to just italicize things than to edit the html and add a bunch of <style=”font-family:courier;”> tags.

HUGE NOTE: As my good friend jblaise pointed out, I am totally wrong about the murdering thing (read Josh’s comment for details). I expected Python to behave like c++ in this way, but apparently this isn’t the case. It doesn’t really matter for the post to still be (mostly) correct, and I feel it would be dishonest to edit what I had written. So, yeah, ignore that stuff.

A while loop is simple. However, there is an important nuance that you have to understand in order to implement it correctly: any variable defined inside the loop is murdered after each run of the loop. MURDERED. [Note: the preceding is what is not actually true]. Also, anything that is indented after the loop is considered to be inside of it. Until it reaches something that is no longer indented. For example:

while True:
    this
    that
    the other thing
something else

The above code will do this, that, and the other thing forever (True is always true… deep, right?). If, magically, True were to become false, then the loop would stop doing this, that and the other thing, and return to the rest of your program, which starts with something else.

Ok, sorry, another sidebar. In programming, there are these things called Boolean values, named after this dude George Bool. Mr Bool suffered brain damage that allowed him to only speak or write the words “true”, “and”, “or”, and “false”. So, in order to communicate, Bool found a way to say all kinds of shit using only those words. We now call this Boolean logic. Booleans can have one of only two possible values: True or False. In Python, these values are represented by True and False (can you guess which one is which?). The first letter must be capitalized, and the rest must not. In other words True != true != TRUE (“!=” means “not equal”). I could go further, but you can play around in the interpreter to get the hang of this (try typing things like True or False, False and False, etc). Oh, and if Python meets something that is supposed to be a boolean, but isn’t, python will define it to be True unless it is zero (0) or some empty data type (like a null string, “”). So while ‘cheese is delicious’: print(‘oh yeah!’) will print “oh yeah!” forever, because it is always True that ‘cheese is delicious’.

Back to the while loop and the murdering. Let’s say that you want to make a variable in this loop, like

while i<3:
    new = 'york'

I don’t know why you would do that, since you hate New York as much as I do, but let’s say that you did. And then you wanted to get the value of new later on in your program:

while i<3:
    new = 'york'
print( new )

You will be disheartened to find that python calls shenanigans and returns an error, because new does not exist outside of that loop. However, if you change a variable that was defined elsewhere, it’s value does actually change.

new = 'york'
print( new )
while i<3:
    new = 'patty'
print( new )

The above code returns >>> “york” >>> “patty”.

Clear? The reason I’m telling you this is because I want to introduce you to a much more awesome loop. It does all kinds of neat things that the while loop can’t do, but requires the user to be a little more clever. It is Windows compared to MacOS.

Meet the “for loop”:

for (each piece) in (this whole):
    (do something)

Besides sounding dirty, what’s going on with that piece-and-whole business? Well, the for loop adapts to your needs by doing different things depending on what values you give it. Let’s say you wanted to do something 10 times. With a while-loop, you might do this:

counter = 0
while counter < 10:
    something
    counter += 1

Pretty simple, with only four lines of code we managed to do something 10 times. Now, with a for-loop:

for i in range(10):
    something

Holy shit! We just halved our code! Maybe not so impressive with only 4 lines… but still. So what is this loop doing? The piece in this case is the variable i, and the whole is range(10). In the case where the whole is a list (range(10) produces a list of numbers from 0 to 9), the piece takes on the first value of that list, runs the for loop, takes on the next value, runs the for loop, and so on until there are no more values in the list. You can name that variable whatever you want (though if you give it a name that’s already used, you’ll overwrite the previous value!). The letter i is just a standard because it is short for index. Let’s try it with something more interesting.

for nuka_cola in range(20):
    print( nuka_cola**2 )

Try it! nuka_cola starts with the value 0, then runs the loop which prints 0 squared (the ** means “to the power of”). Then it takes on the value 1 and does it again. Before you know it, you’ve got a list of squares for the numbers 0-19!
Now you may be asking, “what happens if I put something there that isn’t a list? Or if the list isn’t made of numbers?” Learn by doing (and breaking!). Try the Nuka Cola code, but replace range(20) with “if it bleeds, we can kill it”, a string (so include the quotes). Failure, right? Why?
To figure out what these things are doing, just get rid of the **2 thing. Now you can see what values nuka_cola is taking on. Try it again with the string replaced by a list of strings, (‘if’, ‘it’, ‘bleeds’, ‘we’, ‘can’, ‘kill’, ‘it’).

In short: while-loops are neat, but for-loops are totally badass. Once you master those things, coding will feel like playing Left4Dead 2 instead of like buying DRM-laden music on iTunes. So, take your new toy and go have fun!

2 thoughts on “Python: ad infinitum

  1. Ah! No! Wrong! Scoping (aka murdering) in Python doesn’t work how you’ve explained. The following code runs flawlessly in python2.6 and python3.1 (i.e. it prints york)

    Assuming the tt tag exists in comments:

    i = 2
    while i < 3:
       i += 1
       new = 'york'
    print(new)
    

    This is considered a "feature" and not a bug, even though it has caused MANY headaches. I'm not sure where to find the actual scoping rules for python, but I'm pretty sure once a variable has been assigned a value, it's still alive within the context of a method, even if it was defined within a loop or other indented block. Methods do not share scope (fortunately!), though they all inherit global scope.

    Interesting other point about scoping in Python. Global variables can be overwritten locally, but not globally, unless you declare in the function that you are going to futz with that global variable:

    This code:

    new = 'york'
    
    def adam_func(): # aren't I creative
       i = 3
       if i == 2:
           new = 'york'
       else:
           new = 'car'
       print(new)
    
    print(new)
    adam_func()
    print(new)
    

    Returns: york, car, york

    If we add the line "global new" to the top of adam_func we get york, car, car. BUT if we print(new) at the top of adam_func, we get an UnboundLocalError.

    What the hell python, what the hell?

    1. YOU HAVE JUST CHANGED MY LIFE. Really. I just assumed that Python behaved that way, and never actually tried it… And yes, WordPress is a dick about whitespace. I had to fiddle with this page for a half hour until I finally got it to work (had to use the <pre> tag, since even the <code> tag using &nbsp; didn’t work.

Comments are closed.