Repetition is what computers are really good at; you can ask them to do the same thing over and over again and they will never grow bored. This is the main advantage of using code as a design tool; you don’t have to do everything by yourself again and again. Once your code works for a single case, you can sit back and let the computer handle the next dozen, hundred, or bajillion items.

The for Loop

In programming circles, doing the same thing multiple times is generally called ‘iteration’ or, more colloquially, a ‘loop’. Python provides a concise syntax for looping over a set of values through its ‘for … in …:’ syntax. The first ellipsis should be replaced with a variable name – the loop’s ‘counter’. The second ellipsis should be a list or other sequence type (to be stepped through item-by-item).

The statement should look like this:

for variable in sequence:
    ... # commands

Don’t forget the colon at the end of the for statement! The colon and the indentation of the next line(s) are how Python recognizes the beginning and end of the loop.

The variable part

The variable can have any name you like (as you already know if you’ve read about variables). This variable holds the ‘current’ item as you step through the indented code again and again.

A common name for it is i, especially in cases where you’re looping over a sequence of numbers and the variable is functioning as a ‘counter’. This is an echo from basic math where counters are generally named i as well.

It’s short, and it’s a good convention with a long history.

The sequence part

The sequence part is a collection of elements, most commonly a list. The elements of the sequence can be anything you like: numbers, strings, colors, and so on. Each element is consecutively assigned to the variable.

So if sequence were ["ready", "steady", "GO!"], the commands in the for-loop would be executed three times. The variable will be assigned "ready" the first time through the loop, "steady" the second time, and "GO!" the third time:

for item in ["ready", "steady", "GO!"]:
  print item
>>> ready
>>> steady
>>> GO!

If you want your loop to execute a fixed number of times, try using the built-in range() function. When you use a range, the loop will run once for each value from zero up to (but not including) the number you pass as the range argument.

for item in range(3):
    print item
>>> 0
>>> 1
>>> 2

The commands part

The commands part consists of one or more PlotDevice commands that need to be executed repeatedly. They are indented beneath the for-statement. The script is ‘trapped’ in a loop here and keeps executing the indented commands until each element from list has consecutively been assigned to variable.

What makes this powerful is being able to use the variable’s value in each loop. You’ll notice that in both of the previous examples the commands part is identical. It’s simply printing things out.

Calling print item is an ‘abstract’ command: when PlotDevice goes through the loop item is replaced with each element in the list. Thus you get different output each time the line executes (even though it’s the same code statement every time).

Looping over Collections

You can use either of the collection types (lists or dicts) as the sequence in a loop. So far we’ve seen the ‘typical’ case in which you loop over the elements of a list, but both types provide some handy mechanisms for controlling how you step through them.

Lists

Using a simple ‘for … in’ loop only gives you the values from the list. If you also need the index within the loop, use the convenient enumerate() command. It provides you with a sequence of index/value pairs, one for each item in the list:

shortlist = ['first', 'middle', 'last']
for i, name in enumerate(shortlist):
    print "item", i, "is:", name
>>> item 0 is first
>>> item 1 is middle
>>> item 2 is last

Dictionaries

Dictionaries support the same ‘for … in’ syntax as lists. But where list iteration steps through values, dict iteration steps through keys. Here we iterate through keys and manually retrieve the values from our dictionary:

info = dict(series=9000, instructor="Langley", operational="1992/01/12")
for key in info:
    val = info[key]
    print key, val
>>> series 9000
>>> instructor Langley
>>> operational 1992/01/12

You can also iterate through key/value pairs using the dict.items() method. In this case your for statement should declare two variables (separated by a comma) to refer to the key and value respectively:

for key, val in info.items():
    print key, val

Loops and Randomness

For-loops and the random() command work really well together. You can draw a hundred circles for example, and have PlotDevice place each of them at random locations. This way, each time you run the script, you get a different composition of circles.

It’s easy to program a ‘style’ with variations this way.

... # set up your style

# draw randomly in that style
for i in range(100):
    x = random(HEIGHT)
    y = random(WIDTH)
    r = random(25, 50)
    arc(x, y, r)

Random items from a list

You can let the computer decide on its own which items to draw from the list by using the choice() command. Each time you call choice() it returns a randomly selected value from the list. Since each of these ‘choices’ is independent, it’s quite possible that you’ll receive the same value more than once during a sequnce of calls.

If your goal is to reorder the items in a list while ensuring that each element only appears once, use the shuffled() command. Calling shuffled() doesn’t actually modify the list you pass to it; instead it generates a new, permuted list with the same values as your original. You can store this permutation in another value, or iterate through it immediately:

alphabet = ['a','b','c','d']
print shuffled(alphabet)
>>> ['b', 'c', 'a', 'd']

for letter in shuffled(alphabet):
    print letter
>>> a
>>> c
>>> d
>>> b

Putting it all together

Here’s a dead-simple example of how you would use random choice with small lists to generate compositions. The script defines a pair of lists; one of possible words, and another with selected colors. Everything beyond point in the script is entirely stochastic and will generate different output on every run.

It picks random words and colors from the two lists then draws them to the screen with random sizes and rotations. It retains a certain coherence between different runs because of the limited set of words and colors.

words = ["Lists", "are", "fun"]
colors = [color(1,0,0), color(1,1,1), color(0,0,0)]

for i in range(40):
    x = random(WIDTH)
    y = random(HEIGHT)
    rotate(random(360))
    fontsize(random(10,100))

    fill(choice(colors))
    text(choice(words), x, y)