Python Prerequisites for Data Science Part II: Conditionals, Looping and Functions
This article is Part II for the Python Prerequisites Series about what should be know before starting the Data Science journey. Last time, I covered the topic of Python Data Structures here. Now we will look at conditionals, looping and functions in Python which serve as essential tools in most data related tasks.
Conditionals:
Conditionals are Python statements that control the flow of program via different conditions. The number of conditions can be arbitrary in nature as there is a general structure based on the number of conditions to check. This general structure is illustrated as follows:
if (condition 1):
block of code 1
elif (condition 2):
block of code 2
elif (condition 3):
block of code 3
...
elif (condition n-1):
block of code (n-1)
else:
block of code n
This general structure can be utilized according to the use case i.e. for a single condition (use only if statement), for two conditions (use if-else statement) and for more than two conditions (use if-elif-else structure with as many elifs as needed).
Problem: Check the grade for marks obtained by student B
Consider the following marks associated with the students name for a certain exam, indicated via a dictionary:
Lets assume that the school in which these students study gives grading with A for marks between 86–100, B for marks between 71–85, C for marks 56–70, D for marks 41–55 and F for below or equal to 40, then we can provide conditional statements to check student B’s marks as follows:
Multi-Conditional Check:
Although this works perfectly fine, these conditionals don’t check if marks of students are between 0 or 100. To make sure of those checks, we can make use of two conditions in each line i.e. one for the minimum value and one for maximum value as shown below:
Use cases like these allow to check for multiple conditions at the same time. Normally, there are three logical operators that are used in conditionals i.e.:
- or : Runs block of code if anyone or both of the condition(s) is true
- and: Runs block of code iff all conditions are true
- not: Runs block of code if condition defined is not true
Looping Constructs:
Looping Constructs are used to repeat a certain piece of code a certain defined number of times. Technically, looping constructs come to use when we have to apply the same processing for many values rather than just a single one. Looping constructs can be used in three different styles, each of which is explained with the help of a problem:
First Implementation: For Loop
The for-loop is the first implementation we are going to view for performing the looping process. The general structure for for-loop is as follows:
for i in iterator:
block of code
Here, iterator is a special type of object that allows to loop over its contents one by one (we will see this in detail in the next Part of the Series, but for now that’s all you need to know).
Problem: Check the student with the highest marks with his name and marks
Lets re-consider the marks dictionary, we considered in previous example:
Now lets use the defined dictionary to check the student with the highest marks among the defined students and their respective marks. To implement the solution using for-loop, we can write as follows:
For-loops are used in cases where we have an idea of how many elements we are dealing with (as in case of this marks dictionary of 5 students)
Second Implementation: While Loop
The while-loop is the second way to implement a looping construct in Python. The general structure for while-loop is as follows:
while condition_to_satisfy:
block of code
Problem: Computing average for arbitrary number of expenses
Consider the case of finding average of supplied expenses for a user. According to condition, the input for the user can vary i.e. it may be that he only has 1 expense value to record or maybe 10. Hence, we supply an arbitrary input which would give us a list of values containing expenses. This list can be then used with the while loop to compute average value as shown below:
The output generated in such a case would depend on the number of expenses the user wants to input. A sample output is shown under:
The while-loop is used in cases where we do not know how many elements we are dealing with.
Third Implementation: Infinite While Loop
Infinite While loop is not a new method rather it uses the same while loop but with a different structure as shown under:
while True:
if not condition_to_satisfy:
break
Thus, in infinite-while loop, we always write Boolean value True with the while to keep the loop iterating until the condition to satisfy is not being satisfied anymore. In such a case, the break statement comes into play and terminates the loop. In such cases, we can also use the continue keyword with conditions, which allows to skip to the next loop without processing the code after it.
Problem: Computing average for arbitrary number of expenses with value below 100
We now perform the same task we did in while-loop but this time using the infinite-while structure, with a little catch i.e. the expense entered by the user each turn must be less than 100. We implement this as follows:
The output generated in such a case would depend on the number of expenses the user wants to input and skips over all expenses which are greater than or equal to 100. A sample output is shown under:
Functions:
Functions are an essential part of Python as they allow to create re-usable code blocks for different cases. For suppose we want to compare the marks between two classes, we would need to re-write the code again and then use it for the other class. We can remove such repetitions by making use of Python functions, which would allow us to compute the marks for both classes separately and then compare the result.
Function Definition:
A Python function can be defined using the following structure:
def func_name(func_parameters):
block of code
return output
Here, we have:
- def : keyword to use to create a function
- func_name : Name of the function being defined
- func_parameters: Input values to be provided to a function
- return: Keyword used to return some output on a function call
- output: The value to be returned by the function
Example Implementation:
A simple example of a function might be the square function. It takes some number as input, squares that number and returns the result as output. Hence, functions in programming (or Python) work the same as mathematical functions i.e. take some inputs, process them and return some output. Note that functions are also objects in Python like data structures. We illustrate the implementation of basic square function in Python as follows:
Function Calling:
Functions can be called using the following general syntax:
func_name(func_arguments)
Here, func_arguments are the values to be inputted by the user for the provided parameters. Now, to implement the square function for the value 2, we will call the method as follows:
The thing to note about return keyword in a function is that it gives the value so that it can be stored in some variable unlike print which just displays the value on the screen. To store the output, we just assign the function call to the number of variables equal to number of values being returned by the function. For the square function, only one value is being returned so we can assign it to a single variable
Problem: Check student with maximum marks from given class data
The difference between this and the one previous defined in the for-loop, is that in this case we can reuse the code for different class data at the same time without re-writing the code again. Lets see the implementation:
Problem: Take arbitrary number of expenses from user to compute average
Now lets re-implement the average expense computation. To do this, we can make use of the arbitrary arguments of Python functions so that the user can input all the expense values in one go rather than answering with a ‘y’ before each. This is illustrated as under:
We have taken advantage of the unpacking operation of a tuple when taking the input. These unpacked values can be supplied arbitrarily to the function using the same * operation in the function definition, which allows the function to accept arbitrary number of arguments. The sample output for this case is illustrated as under:
Problem: Check maximum marks for arbitrary number of students
Now lets implement the maximum marks function again but this time with arbitrary number of students. Hence, we can compute for any number of students. This implementation can be done using arguments called “Keyword Arguments” since these arguments are accepted in the form of key:value pair by the function. The implementation is as under:
The above will give the same output as our first problem. The difference here is that we didn’t need to define a dictionary instead we just passed the arguments as key=value and the ** operator allowed to interpret these values as dictionary keys and values respectively on its own. This code returns the following output:
Another thing to note here is the bonus parameter which is already defined as 0 in the function definition. This is known as a “Default Argument” i.e. its value is already defined and if not mentioned in a function call, this default value can be used. We see the application of this bonus in both examples. For class 1, we didn’t define any bonus, so the score of the student with maximum marks remained the same as that defined. However, for class 2, we set a value for bonus marks and it was added to the total marks attained by the student.
Docstring of Function:
Before ending the topic of function, one thing that should be included when defining user made functions is the need of a docstring. A docstring allows the programmer or user using that function to know the purpose of the function and how to use it. In a good docstring, we define the following points:
- Description what the function does
- Description of what the arguments of the function are
- Description of the return values of the function
- Description of the errors raised
- Optimal extra notes for the function
Docstrings are written within triple quotations directly under the function before any of its code. A simple example of a docstring is as follows:
This is a simple function that creates returns an equivalent value for an observation from a normal distribution given the mean and standard deviation. If not given, then it takes a value from the standard normal distribution. To check the docstring of the function, we use the __doc__ attribute that is pre-defined for each function object as follows:
Here we have also used an Exception using the try-except clause, which is used for error handling. I won’t discuss it in detail, but you can check the Python documentation to learn more about it.
That’s it for this Part
With the concepts of conditionals, looping and functions overviewed, our next target would be to cover up the base of looping constructs i.e. Iterators and Iterables. Moreover, we will also dive into the implementations of lambda functions and comprehensions. Looking forward for the next one!
For any queries, contact me at Linkedin: https://www.linkedin.com/in/hassan-farid-5a17541a2/