DRY Out with Loops

If learning to code with foo, bar, and math examples are your kryptonite, keep reading. This series uses relatable examples.

Jump To:

A loop is a set of instructions that gets continually repeated a certain amount of times or until a condition is met. A condition could be waiting for something to be true or false. A condition could also refer to waiting on the loop to run enough times. Let’s go through a pseudocode example of doing introductions in a new group of people. After that, we’ll talk about different types of loops.

# repeat these steps for every person in the group
# say hi
# give your name and pronouns
# say what you like to do when you’re bored
# mention something you could talk about for hours

For Loops

Sometimes we do know exactly how many times we want to repeat our steps or run a loop. When this is the case, we should use a for loop. This doesn’t mean you need to know the exact number of times to repeat the code. I know that sounds contradictory, but I promise it’s not. Knowing the exact number of times to repeat the code can mean that you used some code to explain how many times. We often use len() and range() to get the exact number of repetitions. We’ll go over how range() works then jump into some examples.

From the Python documentation, range() gives a “sequence of numbers and is commonly used for looping a specific number of times in for loops.”

  • range(startNum=0, stopNum, step=1)
    • startNum is the beginning of your range. It’s not required. The default is 0.
    • stopNum is the end of your range.
    • Give only the stopNum and you will get that many numbers, though it will not include the stopNum. This is because computers start counting at 0 and not 1.
    • Give startNum and stopNum and you’ll get numbers from startNum to stopNum, but not including stopNum.
    • step is like counting by 2s (2, 4, 6, 8). If you give it 5 it will give you every 5th number.

Syntax

# get numbers up to, but not including 100
for i in range(0, 100, 20):
    print(i)

Did you notice how there is space in front of all the lines underneath the for line? These are just like the if blocks. The tab before the line is how Python knows this line is a step that belongs to the loop. The next line(s) that are not tabbed in are not part of a loop and therefore will not be repeated. They will run after the loop is done because computers read code top to bottom.

I would read this example as: “for each number from (or “in the range of”) 0 up to but not including 100 while skipping 20, print the number”. The example code would run 5 times. Do you know why? range() is giving us our exact number of times to run the loop. The range starts at 0, ends at but doesn’t include 100, and counts by or steps over 20. In this case, we get 0, 20, 40, 60, and 80.

What is i?

You’ll find outside of giving the syntax above, I will never use i. I find it easier to understand my code when I use a descriptive name. A name is great, but we still need to know what the elusive i is. In a for loop, i is a variable that only gets used within the loop.

This variable is called an iterator variable. It is created in the for line, then it can be used in the block of loop code. With each repetition/iteration of the loop, any uses of the variable in the loop block will change. If the first repetition, the iterator variable was 0, then in the second repetition the iterator variable was 1, and so on.

To make things easier to understand, we could just have easily used num or digit instead of i. Read the syntax to yourself, substituting one of these for the i. Does it make a bit more sense now? Diving into some real-life examples should help explain this better.

Do know that if you’re working with books, tutorials, videos, or even other programmers, they may choose to use i. Know that when you’re reading it, you can substitute what makes sense to you.

What can we do with for loops?

Again, for loops should be used when we want to repeat code and we know how many times to repeat it.

Real-life examples

Have you ever washed dishes before? I have and I really don’t enjoy it. Let’s try setting up some code for a dishwashing robot.

# assume we have a list or sink full of 37 dirty dishes called dirty_dishes_list
# for every dish on the counter, wash it

for dish in dirty_dishes_list:
    add_soap()
    scrub_dish()
    rinse_dish()
    dry_dish()
    print(dish + "has been cleaned")

This DishBot 3000 code won’t work because none of these functions have been made. Instead, they are placeholders in an example. If you want to see it work, you could swap each line for a line like: print("DishBot 3000 has added soap"). We are also missing a dirty_dishes_list. Once you learn about lists, come back to this example, make a dirty_dishes_list, and try out the code.

Since DishBot 3000 is done washing dishes, I think it’s time to make some more dirty dishes while making dinner. Shall we read our recipe and write up some pseudocode?

# recipe pseudocode

# put all ingredients in a bowl
# mix for two minutes

# heat stove and dump mixed ingredients in pot on stove
# mix for five minutes

With our pseudocode recipe done, we can figure out what our code should be. How many of those steps include some sort of repetition? For each step with repetition, we will need another separate loop.

# recipe loops

# put all ingredients in a bowl
for ingredient in ingredients_list:
    print(ingredient, "measured")
    print(ingredient, "added to bowl")

# mix for two minutes
bowl_mix_minutes = 2
for minute in range(bowl_mix_minutes):
    print("mixed ingredients for 1 minute")

# heat stove and dump mixed ingredients in pot on stove
print("Stove is turned on")
print("Mixture has been added to the pot")

# mix for two more minutes
stove_mix_minutes = 5
for minute in range(stove_mix_minutes):
    print("mixed ingredients over heat for 1 minute")

These loop examples won’t work as expected because we are using lists, but haven’t made any lists. We’ll talk about lists soon and you can come back to see how these work out.

Do you recall why the stove heating print statements are not part of any of these loops? If not, hop back to the for loop syntax for a refresher.

Code Behind the .upper() method

Earlier, we talked about the .upper() method. This method takes a string and makes all of the characters uppercase. You now know enough things to write the magic behind .upper(). Let’s pseudocode it first.

# pseudocoding .upper()

# save a string into a variable
# for every character in the string
# if the character is lowercase
# make the character uppercase and print
# if the character is a space, print the space
# if none of that (meaning the character is already uppercase), print the character

Now that you have this written out in pseudocode, use the steps to guide you in writing some code. Don’t forget, you can turn your pseudocode into comments to explain each line. Another hint, programmers tend to use char because it’s short for “character”.

If you don’t recall the ASCII codes for all of the letters, that’s cool, I don’t either. Flip back to String Built-in Functions or lookup “ASCII letter chart”.

Did you notice our pseudocode used the words for and if? We can mix and match our spoken language with the programming language. This helps us start to form an idea of what we should be coding.

I bet you’ll recall that we use tabs and code blocks in both for loops and if blocks. If you use them together, you’ll use combine the tabs to show Python you intend for one to be a part of another. For example, if you have an if block as part of your for loop, the if line will have one tab to show it is part of the for loop. Then, the lines that are part of the if block have two tabs to show it is part of the if block that is inside a for loop.

# coding .upper()

words = "I smelled a goat at the store because I'm a snowman!"

for char in words:  # for every character in the string
    if ord(char) >= 97 and ord(char) <= 122:  # if the character is lowercase
        new_char_code = ord(char) - 32  # get the uppercase character code
        new_char = chr(new_char_code)  # use new_char_code to get uppercase letter
        print(new_char, end="")  # print new_char with no space at end
    elif char == " ":  # if char is a space
        print(" ", end='')
    else:  # if none of the above (probably: char already uppercase or not a letter)
        print(char, end='')

By the way, you can combine functions together. Taking existing code and modifying it to be easier to read and more efficient is called refactoring. With the above example, we could refactor a few lines.

# original lines
new_char_code = ord(char) - 32  # get the uppercase character code
new_char = chr(new_char_code)  # use new_char_code to get uppercase letter

# possible replacement
new_char = chr(ord(char) - 32)  # get uppercase character code then get letter

Why for loops and when to use them?

Without loops, we would have to write a lot more code. That would be a hassle for you, the programmer, and your computer would have bigger files to hold on to. Remember, we use for loops when we can discern exactly how many times we need to repeat the code.

While Loops

Sometimes we really don’t know how many times we want to repeat our steps. When this is the case, we should use a while loop. This means no programmer knows the exact number of times to repeat the code.

Have you ever hit "repeat" on a song? That is a while loop. It's going to repeat until you tell it to stop or until there is no power left for the device. If we were coding, we could say "while there is power, play the song on repeat".

Syntax

counter = 0

while something_true:
    print(counter)
    counter = counter + 1

There are several steps to a while loop. If you skip one of them, your while loop is likely to mess up. Remember, the computer will do what you tell it to, not what you want it to do.

  1. Create the counter - a variable to help know when the loop should end
  2. Give a condition - comparison or logical operator, similar to an if statement
  3. Increment or Decrement the counter - add/subtract every time the loop runs

Avoid Infinite Loops

An infinite loop means code repeats forever until your computer senses it and stops the code. This will often look like your computer or a single program is crashing and not responding. If this is the case, you may need to close the tab or program. Then, go back to your code and make sure you have incremented the counter.

What can we do with while loops?

Again, while loops should be used when we want to repeat code and we don’t know how many times to repeat it. Instead, we give a comparison(s) or logical operator(s) to make a condition.

Real-life examples

# first ask the cat how many times they’d like to be pet, but don’t tell the human
preferred_pets_num = int(input("How many times would you like to be pet"))
pet_attempts = 0  # start with 0

while preferred_pets_num > pet_attempts:
    print("You have consent to pet again")
    print("purrrr, that pet was accepted")
    pet_attempts = pet_attempts + 1  # add 1 every time you pet

print("That was 1 too many times. I'm leaving now")

The three tabbed in lines run once for each repetition of the loop. The loop ends when we have gone over the accepted amount of pets. Now that the loop is over, we can print that the cat has decided to leave.

Now that the cat is upset and has left us, let’s check the weather and see if our dog is ready to play. In this example, we’ll combine a bunch of the things we’ve covered like if-then statements, logical operators, casting strings, and a while loop. It’s longer than some of the other examples. We’ll look at the different parts to make it make sense.

dog_wants_to_play = True  # dog always wants to play
sunny_outside = bool(input("Sunny? True/False"))
rainy_outside = bool(input("Raining? True/False"))
warm_outside = bool(input("Warm outside? True/False"))
cold_outside = bool(input("Cold outside? True/False"))

dog_energy = 100  # starting with 100%
outside_spent_energy = 3  # % energy spent fetching one time
inside_spent_energy = 2  # % energy spent fetching one time

while dog_energy > 50:  # gotta leave pup some energy
    if sunny_outside and warm_outside:
    go_outside()  # sets outside to True
    if outside:
        throw_ball()
        print("Go get it!")
        print("Drop it")
        dog_energy = dog_energy - outside_spent_energy
    elif rainy_outside or cold_outside:
        throw_ball()  # throw carefully, you're inside
        print("Go get it!")
        dog_energy = dog_energy - inside_spent_energy
  • At the top, first chunk of lines, we have some inputs that will later help us decide when and where to play. I would read the second line as: “getting user input string of True or False, cast or force into a boolean, then saved into variable sunny_outside”.
  • After the inputs, we have three lines that set up our dog’s energy. I’d read these as “dog starts with 100% energy, 3% energy is spent outside, and 2% energy is spent inside.” Now we can get into our while loop. Our first line of the loop could read as “while the dog has more than 50% energy, then we do the stuff below”.
  • Looks like we’ve run into an if-elif statement. Depending on the inputs, you’ll only do one or the other. There are two options: “If it’s sunny and warm, then do the code in this block” or “If it’s rainy or cold, then do the code in this block”.
  • At the end of each of the if and elif blocks, we made sure to account for spent energy and subtract from dog’s energy. You could read that line as “current dog’s energy is now = the old dog’s energy minus energy spent”. Without this line, we’d have an infinite loop and our poor dog would be so tired they may get hurt.

Do know, this code won’t work as is because none of these functions have been made. Instead, they are placeholders in an example. If you want to see it work, you could swap each fake function (go_outside() and throw_ball()) for a line like: print("We are outside now."). You would also have to change if outside: to if True:.

We talked about infinite loops earlier, but they’re generally a computer or human problem. There are infinite loops in real life. Do you know about the water cycle? The basic concept doesn’t have a good starting point because it is always happening. So, let’s start with rain, snow, and any other precipitation. Water, in some form, falls from the sky. Then, this water collects somewhere (eg bucket, ocean, lake etc). Once the water collects, it can evaporate. As it evaporates, clouds form and the cycle continues until the end of Earth.

If you run try writing this code, expect it to crash. If you don’t remember why that’s fine. You can jump back to the section on infinite loops.

earth_exists = True

# while the earth_exists
# water falls back to earth - precipitate
# water collects
# water evaporates
# clouds form - condensation

Behind the Scenes: Winning and Losing

Using while loops and if-else statements we can build scoring for your favorite game. No matter the complexity of the scoring, you can write it with while loops and if-else statements. First, we’ll use a coin-flipping game.

Our first step won’t be in a while loop. We’ll add the loop when we adjust the game to have 3 rounds and whoever gets two out of 3 will win. Coins have two sides. We’ll call one side “heads” and the other “tails”. Player one, the computer, flips the coin while player two, you, say which side they think will land facing up. If player two’s choice has landed facing up, they win.

your_choice = input("Heads or Tails?").lower()
coin_landed = "heads"

if coin_landed == your_choice:
    print("You win")
else:
    print("You lost")

For now, we have “hard coded” which side of the coin landed facing up. Hard coding means that we did not use any programming magic to come up with this. Instead, we told it the answer. Later when we talk about Python lists, we will add a couple of things to make the computer’s coin flipping random.

For now, we know who won this game but we should make this fair and try for the best two out of three rounds.

rounds_won = 0  # start with 0
rounds_lost = 0  # start with 0
total_rounds = 0  # start with 0

while total_rounds < 3:
    your_choice = input("Heads or Tails?").lower()
    coin_landed = "heads"  # you can change this
    if coin_landed == your_choice:
        print("You win this round")
        rounds_won = rounds_won + 1
    else:
        print("You lost this round")
        rounds_lost = rounds_lost + 1
total_rounds = total_rounds + 1

# calculate who won
if total_rounds == 3 and rounds_won >= 2:
    print("You win! You got best 2 out of 3")
else:
    print("You lose! Computer got best 2 out of 3")
  • At the top, the first chunk of lines, we added in some counters to help run the code.
  • After the counters, we added a while loop and tabbed in the if-else statements and their blocks.
  • With the input().lower() we are acknowledging that a player may input something with different capitalization and we are making sure it will match out coin_landed exactly.
  • Looks like we’ve run into an if-else statement. Depending on the outcome of the round, you’ll only do one or the other. There are two options: “the coin side facing up is the same as your choice, then do the code in this block” or “the coin side facing up is not the same as your choice, then do the code in this block”.
  • At the end of each of the if and else blocks, we made sure to account for the results of the round. Depending on the block, you could read that line as “current rounds won = the old rounds won plus one” or “current rounds lost = the old rounds lost plus one”.
  • After the else block, but still part of the while loop, we add one to our total rounds. Without this line, we’d have an infinite loop and our game would never end.
  • At the very end, after the loop ends, we use another if-else statement to decide who won the whole game.

Did you notice how we coded the important guts of the game first, then we added the extra features? This is a typical approach to coding. First, we build a functional project. Once it works, we can add features to it. This helps us keep from getting overwhelmed and allows us to see working parts sooner.

Why while loops and when to use them?

Remember, we use while loops when we cannot know exactly how many times we need to repeat the code.

Do you remember?

Here's some practice challenges. Let’s practice what we’ve learned so far. Go ahead and comment on this post with your answers. Do you remember? If not, you can always go back to read sections again.

Give a real-life example of a for loop and a while loop

You can use print statements or fake functions (like jump() or turn_wheel()) to fill in the if-elif-else then blocks

# coding a for loop
# coding a while loop

What’s Wrong with These? Can You Fix them?

There may be multiple ways to fix these. Have fun and do it whatever way you think makes sense.

# pets are a mix of birds, fish, cats, dogs, and reptiles
    for pet in the range of 1 to 10
feed_pet()
brush_pet()
give_water()
    take_outside()
play()
while dog_awake:
        if dog_energy is more than 50;
    dog_awake = True
    dog_energy = 100
    chase_cat()
    chew_toy()
    beg_for_pets()
    dog_energy = dog_energy - 5
        else:  # dog_energy low
    nap_time()  # changes dog_awake to False
    print("It’s doggy nap time!")

Go Ahead! You can build it! .lower()

# coding .lower()

and maybe even .title()

# coding .title()

You got this! Build Scoring for a game

You can use print statements or fake functions (like throw() or move_left()) to fill in the if-elif-else then blocks.

# scoring for any game

Thank you to @yechielk for reviewing. If you like learning about how ethics and programming go together, check out their book and newsletter.

22