Technology Entrepreneur, Software Architect Freelancer, Student of Statistics, Neuroscience, and Machine Learning.
by Ashraf Ahmed
At their essence, programming languages are composed of a set of symbols and rules. A computer program is a collection of instructions composed in a certain way to perform certain activities https://en.wikipedia.org/wiki/Computer_programming. The goal of any computer program is to provide a set of instruction to a microprocessor.
One way to classify programming languages is based on how well those hardware instructions are abstracted. A high-level programming language provides a high-level of abstraction from the microprocessor instruction set while a low-level programming language provides no level of abstraction from the microprocessor instruction set. In essence, in the highest of programming languages, you don’t even need to know about the underlying components of the computer.
Python is a high-level general purpose programming language. General purpose because the language can be used in many domains, including Science, Banking, Engineering, Accounting …etc. In python, you don’t even need to know what the microprocessor is doing at a given time.
It is very natural to think of repeating a set of instructions to perform a certain activity. Some useful examples are:
Let’s take a dictionary example. In this example, you’ve a python variable that holds the entire English language dictionary, stored as a python dictionary. As you recall from Datacamp courses. A python dictionary is a collection of key value pair entries. In this case, the key is an English word, while the value of that key is the meaning of that word in an English language dictionary. Below is an example of a three word dictionary:
english_dictionary = {
"swim": "verb, to move in water by movements of the limbs, fins, tail, etc.",
"bike": "verb, to ride a bike",
"run": "to go quickly by moving the legs more rapidly than at a walk and in such a manner that for an instant in each step all or both feet are off the ground.",
"data": "noun, plural of datum"
}
It is very natural to ask, how can I search such a dictionary? A more experienced python programmer might say, use the dictionary function get(). The function get takes a key and returns the value of that key. For the sake of this writing, we are going to assume that you are now part of the Python language development team and you were tasked with building such a function.
Before we talk about how we can write such a function in Python, we might want to think first about a set of instructions that anyone can perform, a computer or otherwise. Here is a possible set:
At that point you should notice, things are repeating, this is an iterative algorithm.
Python have different control structures to let you express that pseudo code. Here is a possible program
english_dictionary = {
"swim": "verb, to move in water by movements of the limbs, fins, tail, etc.",
"bike": "verb, to ride a bike",
"run": "to go quickly by moving the legs more rapidly than at a walk and in such a manner that for an instant in each step all or both feet are off the ground.",
"data": "noun, plural of datum"
}
interesting_word = "data"
for key, value in english_dictionary.items():
if key == interesting_word:
print(
"Found the meaning of the word " + key + " which is '" + value + "'"
)
print("Done searching the entire dictionary!")
You might realize that we aren’t explicitly telling python how to go to the next item in the list. This is because python knows how to do that. This is the beauty of this snippet:
for key, value in english_dictionary.items():
Since this demo is about showcasing different ways of expressing loops in Python, we need to start thinking, how can we implement this algorithm using other iterative instructions?
A major difference between why loops and for loops is based on the semantics of the iterative instruction. In a while loop, we don’t define what we are iterating over. On the other hand, in a for loop you have to specify the list you are iterating over. Notice how in the for loop example, you had to specify english_dictionary.items() which is a collection if key value pairs of the dictionary entries.
Let’s try and think of how we might invent an algorithm to do exactly what we want but without specifying the collection of dictionary entries. One possible algorithm is as follows:
Here is how that looks in python.
english_dictionary_item_list = list(english_dictionary)
current_index = 0
while current_index < len(english_dictionary_item_list):
current_word = english_dictionary_item_list[current_index]
if current_word == interesting_word:
print("Found the meaning of the word " + key + " which is '" + value + "'")
break
else:
current_index = current_index + 1
print("Done searching the entire dictionary!")
Why would the python language designers provide us with 2 different loop instructions? Isn’t it redundant?. If you are new to python, you might think that those two iterative instructions are the same. Those iterative instructions actually provide very different semantics. The for loop structure lends itself better to situations where the iterative algorithm has to sequentially scan a given collection. The while loop structure on the other hand doesn’t care if it is iterating over a collection or not. Here is an algorithm that lends itself more to the while loop:
x = 5
temp = x
factorial = 1
while temp > 0:
factorial = factorial * temp
temp = temp - 1
print("The factorial of " + str(x) + " is " + str(factorial))
Let’s unpack this example a little. Here, we are calculating the factorial of a given number (Factorials do arise in many probability distributions as well as in simple counting). In this case, we don’t have a set of numbers to iterate over in a for loop. We had to define a stopping condition. In this case, the stopping condition was that we reached 0 (recall that the factorial of 0 is 1). Technically speaking we can make this a for loop, to do so we will need to generate a list of numbers to use. here is how you would do it in a for loop:
x = 5
factorial = 1
for temp in [5, 4, 3, 2, 1]:
factorial = factorial * temp
print("The factorial of " + str(x) + " is " + str(factorial))
This was made possible because of the collection [5, 4, 3, 2, 1]. What if we wanted to calculate the factorial of 100? You probably don’t want to write 100, 99, … all the way to 1. You might think, why don’t we generate that list? Even so, to generate that list you would need a while loop. If you know about the Python range function, you probably know that you can generate such a list but that isn’t the point we are trying to make. The point is this, for loops requires a collection to iterate over, while loops dont. While loops are far more flexible.
Python is a very popular language and for a very good reason. One of those reasons is list comprehensions. In list comprehensions, you are able to iterate over a collection of items in a very compact form. Let’s write a list comprehension to perform the dictionary search we performed earlier.
[print(x) for x in list(english_dictionary.items()) if x[0] == interesting_word]
List comprehensions are much more compact than either for loops or while loops. They’ve all the ingredients of the for loop but without the bulk. A For loop is still very useful in those situations where you want to do a lot of work in every iteration. In this example, all we are doing is filtering the dictionary based on a value of one of the keys. A simple task fit for a list comprehension.
For more about list comprehensions, visit https://realpython.com/list-comprehension-python/.