Topic 1: For Loops and Iterables

What is a For loop?

"For loops" in Python are used to iterate over an iterable (we'll get to that later), which is different than For loops in other programming languages like C. This may be unorthadox, but let's discuss a For loop in C first. An example of a typical For loop in C looks like this:

for( x=3 ; x<=18; x=x+3 ) 
{
  printf("%d\n", x );
}

The For loop in C has a simple consistent structure which is for (init; condition; modify). The init statement is executed once before anything else. In the example above, the variable x is initialized to a value of 3. Each time before executing the contents of the loop, the condition statement is evaluated. In the example above, the value of x is evaluated to be less than or equal to 18. If this condition statement evaluates as True, the contents of the loop are executed. In this case (ignoring the odd syntax of the print statement) this just prints the value of x. After the contents of the loop are executed, the variable x is modified according to the modify statement, which in this case, increases the current value of x by 3. The For statement continues to execute the contents of the loop (printing x) and modifying the value of x (incrementing by 3), as long as the condition statement continues to be True. When this For loop is executed, the output looks like this.

3
6
9
12
15
18

To get the same behavior in Python, the For loop code would look like this:

for x in range(3,19,3):
    print(x)

And the output would also look like this.

3
6
9
12
15
18

Ignoring the syntax differences between Python and C, the important difference is in the structure of the Python For loop, and understanding what the range() function is doing. To understand this, let's talk about iterables.

What is an iterable?

One of the more powerful capabilities in Python is its ability to iterate through something that it recognizes as a sequence. From Python's Glossary, the the official definition of an iterable is "an object capable of returning its members one at a time. Examples of iterables include all sequence types (such as list, str, and tuple)". The range() function returns a list of numbers, and for each value in the list, python assigns the value to x and executes the loop code once. It is important to note that Python iterates through the sequence in the order, first to last, and that the looping ends when the sequence is complete.

Although the use of the range() function is common for Python For loops, the Python example above could have been written as shown below using a simple list. It is important to note that the output of the range() function is a List, which Python recognizes as a sequnce of values that it knows how to return one at a time. The returned list is therefore an iterable.

for x in [3,6,9,12,15,18]:
    print(x)

Basic Usage Examples

For iterating through a loop 1000 times, writing out the entire list would be tedious and wasteful. This is why having a range() function to be able to quickly generate an iterable list is so convenient.

for x in range(1000):
    print(x)

Note: if only a single value is provided to range(), an initial value of 0, and an incremental change of +1 is assumed. The list produced by range(1000) would be [0,1,2,3... 998,999]. The final value is up to but not including 1000. This is why the range function used with the C example had 19 as the final value. This ensured that 18 was included in the list.

Before moving on, let's repeat an important point. Python will always iterate through a list in the order of first to last. This means that if the values in the list were "not in order", Python will still return the values from first to last, regardless of value. For example, executing the following code...

for x in [12,4,7,32]:
    print(x)

Results in the following output, which is exactly in the order that they appeared in the list.

12
4
7
32

Even though the values in a list may not appear to be in any particular order, a list in Python always has an order to it. In the example above, the value 12 is in the first position (index position 0), and the value 7 is in the third position (index position 2).

Although an in-depth discussion of Lists is best left for later, a little better understanding of list indexes is needed before discussing the next iteration method. In the example below, a list called myList is given the values [12,4,7,32]. There are then two print statements that print the values of the list at index positions 0 and 2.

myList = [12,4,7,32]
print(myList[0])
print(myList[2])

When this code is executed, the resulting output is this.

12
7

Another common iteration method is to use a combination of the built-in functions len() and range() to iterate through a list (or other iterable) by index. An example of the common usage is shown below.

myList = [12,4,7,32]
for x in range(len(myList)):
    print(x)

When this code is executed, the resulting output is this.

0
1
2
3

That may not be what you expected, but it is correct. What we asked Python to do was find the length of MyList, which is 4, and to have range create a list of length 4 starting at 0, which it did. The For loop then iterated through the list returned by range, which was [0,1,2,3]. This represents all of the valid index positions of myList. In order to get the values from myList as we did before, we need to use x as the list index. To demonstrate that this gives us more information than before, let's print both the index and the value at the same time, like this:

myList = [12,4,7,32]
for x in range(len(myList)):
    print(x, myList[x])

Now when the code is executed, we get both the index and the value for each position in myList.

0 12
1 4
2 7
3 32

Before moving on, try some experimentation. There is a great on-line resource for Python For Loops at w3schools. Take a look at this. They provide several interactive examples, including iterating through strings, breaking out of a For loop, nested For loops, and much more. w3schools.com is one of my favorite resources. They do a great job.

Is that It? Can I Only Iterate Through Lists, Strings, and Tuples?

No. Those are just the typical Python iterables. Many things that are not inherently iterable, can be made iterable, for example, a Python Dictionary. Additionally, many things that you wouldn't expect to be iterable are, for example when reading files. These are definitely not the only examples. I have learned that Python is too large and evolving too quickly for me to know everything that is or could be made iterable. I would recommend that you do what I do. Take notes on the things that you discover, but limit it to things that you will likely use again. Python is easy to learn, but trying to become an expert in every aspect of Python would take more than a lifetime.

NOTE: In Python 3 it is possible to directly iterate using a Dictionary. The effect is that the keys() iterator function will be called implicitly. Personally, I prefer to be explicit whereever possible, as it enhances maintainability. I would recommend using keys() anyway.

Iterating Through a Dictionary

Before getting started, it's probably a good idea to check out this on-line resource for Python Dictionaries at w3schools. A dictionary is a collection which is unordered, changeable and indexed. A good example for a Dictionary would be a shopping list. It doesn't matter where an item like "Apples" occurs in the list, only that it exists or doesn't exist, and if it does exist, has a value indicating how many to buy. Originally Python didn't know how to iterate through a dictionary, so member functions were required to return an iterable item from the dictionary. The example below shows the creation of a Python Dictionary, and a For loop which iterates through the list returned by keys().

myDict = {
    "Apples": 3,
    "Bananas": 2,
    "Cucumbers": 4,
    "Doughnuts": 6 }
for x in myDict.keys():
    print(x)

When the code is executed, an output of the items of the shoping list is produced. These are the keys of the dictionary.

Apples
Bananas
Cucumbers
Doughnuts

If what you wanted was to iterate through the values by themselves. Something that doesn't seem very useful for a shopping list, but could be for a dictionary that held a different type of data, then the member function values() can be used instead.

myDict = {
    "Apples": 3,
    "Bananas": 2,
    "Cucumbers": 4,
    "Doughnuts": 6 }
for x in myDict.values():
    print(x)

When the code is executed, an output of the quantities in the shoping list is produced. These are the values of the dictionary.

3
2
4
6

CAUTION: Although the outputs from the examples above appear to be "ordered", the items in a Python Dictionary are not guaranteed to be in any particular order! Never count on the ordering of the keys or values from a dictionary.

If it is desired to extract both the key and value simultaneously from a dictionary, the items() method function can be used. This function returns a list of tuples that contain the key and value combinations. By using the Python assignment convention shown below, Python understands that what you want is to assign the first value (the key) to x and the second value (the value) to y. This allows you to use the key and value from each tuple simultaneously.

myDict = {
    "Apples": 3,
    "Bananas": 2,
    "Cucumbers": 4,
    "Doughnuts": 6 }
for x, y in myDict.items():
    print(x, y)

When the code above is executed, an output of both the items, and thier associated quantities in the shoping list is produced.

Apples 3
Bananas 2
Cucumbers 4
Doughnuts 6

In Python there are typically several ways to accomplish most tasks. The same output from the example above using items() could have been accomplished using the keys() function combined with accessing the associated value using the key in brackets.

myDict = {
    "Apples": 3,
    "Bananas": 2,
    "Cucumbers": 4,
    "Doughnuts": 6 }
for x in myDict.keys():
    print(x, myDict[x])

When the code above is executed, an output of both the items, and thier associated quantities in the shoping list is produced.

Apples 3
Bananas 2
Cucumbers 4
Doughnuts 6

It's possible, depending on your familiarity with Python, that you may be asking "what the heck is a tuple?" or "how did Python know to assign different values to x and y?". Unfortunately these are questions for a different Topic discussion, but... It's probably a good time to recommend looking at the output of various functions before using them in a For loop. The example below prints the output of the various iterator functions used in the examples above.

myDict = {
    "Apples": 3,
    "Bananas": 2,
    "Cucumbers": 4,
    "Doughnuts": 6 }
print("----------------")
print(range(len(myDict)))
print("----------------")
print(myDict.keys())
print("----------------")
print(myDict.values())
print("----------------")
print(myDict.items())

When the code above is executed, the following outputs are produced. And... That's not what I expected.

----------------
range(0, 4)
----------------
dict_keys(['Apples', 'Bananas', 'Cucumbers', 'Doughnuts'])
----------------
dict_values([3, 2, 4, 6])
----------------
dict_items([('Apples', 3), ('Bananas', 2), ('Cucumbers', 4), ('Doughnuts', 6)])

NOTE: In Python 2 the output of most iterator functions such as range(n) output a simple list. In Python 3, these now generate iterators, which are "iterable objects". Apparently this was done for memory management reasons. Unfortunately, it may not provide the output you're looking for. For example, the output range(0, 4), is that 4 inclusive, or not inclusive? If you want to see the underlying List, as in Python 2, use the list()function.

The example above is shown again below, this time using list().

myDict = {
    "Apples": 3,
    "Bananas": 2,
    "Cucumbers": 4,
    "Doughnuts": 6 }
print("----------------")
print(list(range(len(myDict))))
print("----------------")
print(list(myDict.keys()))
print("----------------")
print(list(myDict.values()))
print("----------------")
print(list(myDict.items()))

When the code above is executed, the following output is produced. This certainly makes it clearer that the 4 in range(0, 4) is not inclusive.

----------------
[0, 1, 2, 3]
----------------
['Apples', 'Bananas', 'Cucumbers', 'Doughnuts']
----------------
[3, 2, 4, 6]
----------------
[('Apples', 3), ('Bananas', 2), ('Cucumbers', 4), ('Doughnuts', 6)]

I was going to cover iterating through files (yes that's a thing), but that's probably best left to it's own Topic. Within this initial Topic discussion I found myself wanting to print something more descriptive than just an object. The next Topic will be on Fancier Output Formatting. That will allow me to make the printed output in future Topics a little nicer.