for
¶The basic idea of the for
loop is for you to be able to execute some block of code for each element of a list/sequence.
Let's now expand what we can do with that idea...
Challenge 1: how do we do something X times (where X might be large?)
num_times = 20
# we need a list or sequence of length 100
long_string = "a" * num_times
long_list = [1] * num_times
# _ is our way of saying we don't
# actually care what is in the list
for _ in long_string: # could also have been long_list
print("I will practice programming everyday!")
# In retrospect, we made something big and didn't actually care about
# what we made... that seems sad & wasteful :(
Challenge 2: how do we output how many times we've done something?
num_times = 20
count = 0
for _ in ("a"*num_times):
print("{}. I will practice programming everyday!".format(count+1))
count = count + 1
Challenge 3: how do we systematically skip elements in a list?
mylist = ['important', 'not', 'really important', 'so not important', '!!!', ';)']
# so...
# 0 = keep
# 1 = don't keep
# 2 = keep
# 3 = don't keep
# 4 = keep
# 5 = don't keep
# pattern?
count = 0
for element in mylist:
if count % 2 == 0:
print(element)
count += 1
Challenge 4: how do we work with multiple lists at once!?
mynames = ["alice", "bob", "carol"]
myages = [28, 44, 57]
myfaves = ["programming", "traveling", "hugging pandas"]
count = 0
for name in mynames:
print("{} is {} years old and really likes {}".format(name, myages[count], myfaves[count]))
count += 1
range
¶The range
function "creates" a numerical list on-the-fly based upon arguments you supply, including the starting value (inclusive), the ending value (exclusive), and the step we take between each value.
Note: it doesn't really create the underlying list unless you ask (e.g., via the list
function), but acts this way for purposes of a for
loop (so just as good, but not as wasteful).
# Only requirement is upper bound: assumes lower=0, step=1
print(list(range(5)))
# Starts at 1, upper bound is 5; assumes step=1
print(list(range(1, 5)))
# No assumptions made :)
print(list(range(1, 5, 2)))
So back to Challenge 1 (doing something X times)...
num_times = 20
for _ in range(num_times):
print("I will practice programming everyday!")
And Challenge 2 (how many times we've done something)...
num_times = 20
# Note, we now care about which element we're on...
# it takes the place of our counter!
for count in range(num_times):
print("{}. I will practice programming everyday!".format(count+1))
And Challenge 3 (systematic skipping)...
mylist = ['important', 'not', 'really important', 'so not important', '!!!', ';)']
# First step: what do we supply to range when using a list?
# Answer: range(len(mylist))
for iteration in range(len(mylist)):
print("all: " + mylist[iteration])
print()
# So now on to skipping
# Option 1: if
for iteration in range(len(mylist)):
if iteration % 2 == 0:
print("keep 1: " + mylist[iteration])
print()
# Option 2: if the pattern is easy, use range!
for iteration in range(0, len(mylist), 2):
print("keep 2: " + mylist[iteration])
And Challenge 4 (multiple lists)...
mynames = ["alice", "bob", "carol"]
myages = [28, 44, 57]
myfaves = ["programming", "traveling", "hugging pandas"]
for iteration in range(len(mynames)):
print("{} is {} years old and really likes {}".format(name, myages[iteration], myfaves[iteration]))
enumerate
and zip
¶The enumerate
function allows you to loop over the index and value of list/sequence elements at the same time...
mylist = ['important', 'not', 'really important', 'so not important', '!!!', ';)']
for iteration, element in enumerate(mylist):
print("Index={}, Value={}".format(iteration, element))
print()
for charnum, character in enumerate("word"):
print("Index={}, Value={}".format(charnum, character))
So let's revisit Challenge 3 for yet another option...
for iteration, element in enumerate(mylist):
if iteration % 2 == 0:
print(element)
The zip
function allows you to loop over multiple lists in parallel...
mynames = ["alice", "bob", "carol"]
myages = [28, 44, 57]
myfaves = ["programming", "traveling", "hugging pandas"]
for name, age, fave in zip(mynames, myages, myfaves):
print("{} is {} years old and really likes {}".format(name, age, fave))
while
¶The for
loop is super useful when you are performing the same operation for a known duration/sequence.
But what about when you do NOT know ahead of time when to stop, such as when validating input or waiting for a certain condition to hold...
joke = ""
count = 0
while joke != "quit":
joke = input("Please tell me a joke: ")
count += 1
print("Ha" * count)
print("Wow, my ribs hurt... ;)")
Another example is an iterative algorithm, where each loop iteration gets closer to an answer (but you might not want to wait 5 years for an answer!)...
# Adapted from Text (8.6)
# Let's approximate the square root of a number, n
n = 289
max_iterations = 10
count = 1
approx = 0.5 * n
better = 0.5 * (approx + n/approx)
while (better != approx) and (count < max_iterations):
approx = better
better = 0.5 * (approx + n/approx)
count += 1
print("After {} iterations, sqrt({})={}".format(count, n, approx))
Note the similarity of syntax/interpretation with an if
statement -- but whereas if checks the condition (and potentially executes the block) once, while
continues as long as the condition holds.