OPS445 Lab 3: Difference between revisions

From Littlesvr Wiki
Jump to navigation Jump to search
No edit summary
 
(16 intermediate revisions by the same user not shown)
Line 1: Line 1:
= !!!THIS LAB IS NOT READY YET!!! =
= Functions =


= INVESTIGATION 1: CREATING THE SIMPLEST FUNCTIONS =
You can think of a '''function''' as a '''smaller program within a larger program'''. The purpose of a function is to help you avoid copy-pasting the same code into multiple places in your program. That may sound like not a big deal, but with any amount of experience you'd find that such copy-pasting inevitably leads to big, unexpected problems. Just imagine for example:


:A very simple definition of using '''functions''' is to create and reuse '''smaller programs within a larger program'''. In programming languages such as '''C''', '''C++''' and '''Java''', commonly used functions are pre-packaged in '''libraries'''. This relates to dependency issues that were discussed when compiling C programming code in your OPS235 course: if a supporting library is missing, the program would not be able to run the called function.
# You wrote two pages of code, and it seemed to work,
# You copied the apparently working code to 23 places in your large and complicated program,  
# You had to modify the code slightly in 12 of the 23 places,
# 6 months later you found a bug in the original code.
# You fixed the original code, and copied it to 21 places, forgetting to modify it as needed in 3 of the 12 places.


:Usually, a '''function''' will '''contain programming code''' in some part of the python file (most likely near the top of the file, before the main program). We refer to that as a '''"function declaration"'''.
In that scenario, especially under the stress programmers usually are: you will almost certainly end up making a mistake similar to #5, and your one bug which should have been easy enough to fix turned into 4 new bugs in code that was already tested and working, and those 4 bugs may not even be discovered for another year.
: When a program is run, the '''function's code is read into internal memory''', ready to be run when the function is executed (referred to as '''calling the function''').  Until a Function is specifically told to execute, its code will sit (in internal memory) unused.


:When creating programs that define and use functions, '''a large programming task can be broken-down into smaller elements''' (or '''modules'''). This is why creating programs that use functions is referred to as '''"modular programming"'''.
This is the real value in functions. Building useful functions is not a trivial process, but with experience it will become more and more obvious to you what makes a good function, and when it is worth the effort to create one.


== PART 1 - How User-Defined Functions are Declared and Run ==
In our simple examples: a function is '''defined''' near the top of the file, before the main program. When a program is run, the function's code is read into RAM, ready to be run when the function is '''called'''.  Until a Function is explicitly called, its code will sit (in RAM) unused.


:Functions may be designed:
A function may do one ore more of the following:
* '''not to accept arguments or return a value''',
# Run some useful code
* to '''not accept arguments but return a value''',
# Return a useful value
* to '''accept arguments and not return a value''',
# Receive one or more parameters from the caller
* or to '''both accept arguments and return a value'''.
In this investigation, we will focus on creating functions that either do NOT return a value, or return a value.


'''Functions and Strings'''
What your function should do depends on what you want/need it to do, but '''#1''' is almost universal, and '''#2''' is almost always done.


: You will now learn how to define and run functions that will return '''string data''' when a function is called.
Like most of the examples in this course: you have to use your imagination to understand the potential value of these things. The examples are purposefully trivial, to help you understand the basics before you get into actually useful code.


:'''Perform the Following Steps:'''
== Simple functions with strings ==


:#Create a new python file for testing code in this section.
You will now learn how to define and run functions that will return '''string data''' when a function is called.
:#Whenever you want to create a function, you must start with the keyword "'''def'''". The '''def''' keyword is used to start the definition of the function, it does not run the code you write. Functions, just like '''if''' statements, must have all code under them indented.<source lang="python">
 
* Create a new python file for testing code in this section.
Whenever you want to create a function, you must start with the keyword "'''def'''". The '''def''' keyword is used to start the definition of the function, it does not run the code you write. Functions, just like '''if''' statements, must have all code under them indented.
* Create a function called hello():<syntaxhighlight lang="python">
def hello():
def hello():
     print('Hello World')
     print('Hello World')
     print('Inside a Function')
     print('Inside a Function')
</source>
</syntaxhighlight>
:#Executing your file you should have noticed that nothing happened. Well actually, something did happen... the function called '''hello(''') has been defined and stored in internal memory in order for it to run when called by its function name. Now that our function was created, we can use it over and over.
* Run your program and note that nothing seems to happen. Actually something did happen: the function called '''hello(''') has been defined and stored in RAM in order for it to run when called by its function name. But it was never called, so it never printed anything.
:#To execute the code inside the function, run the function name with "'''()'''" '''brackets''' at the end of the function name.<br>Try running the '''hello()''' function by name three times like this:<source lang="python">
* Now that our function was created, we can use it over and over.
* To execute the code inside the function, you call it by using the function name followed by one open round bracket and one closed round bracket. Call your '''hello()''' function by name three times like this (make sure the calls to hello() are not inside hello(), which is determined by the indentation of the calls:<syntaxhighlight lang="python">
hello()
hello()
hello()
hello()
hello()
hello()
</source>You should notice that the function just does the same thing over-and-over no matter how many times your call the function by name. By the way, that is OK. On the other hand, you may want to create and use a function to do something, like perform error checking or some other task that returns a value to the '''main''' program for further processing. For example, a '''true''' or '''false''' value if the error checking function that was called was detected no errors or detected an error. But let's stick to some simple examples first, before tackling more complex use of functions.<br><br>
</syntaxhighlight>
:#Let's create a function that '''returns''' some data after the function is called. This function does not print out any text: instead; it creates new variables and at the end returns the value of one of the variables.<source lang="python">
 
Notice that the function just does the exact same thing no matter how many times your call the function by name. Sometimes that's what you want. At other times you may want your function to work on data which was not there when you wrote your function: for example perform error checking or some other task that returns a value to the '''main''' program for further processing.
 
* Create a function that '''returns''' some data to the caller after it is finished. This function does not print out any text: instead; it creates new variables and at the end returns the value of one of the variables.<syntaxhighlight lang="python">
def return_text_value():
def return_text_value():
     name = 'Terry'
     name = 'Terry'
     greeting = 'Good Morning ' + name  
     greeting = 'Good Morning ' + name  
     return greeting
     return greeting
</source>
</syntaxhighlight>
:# Call the function like this:<source lang="python">
* Call the function like this:<syntaxhighlight lang="python">
return_text_value()
return_text_value()
</source>One major difference between a function '''returning a value''' and simply '''printing a value''' is that '''returned''' values can be caught and stored in variables used in the program (that called the function) for later use. Once the returned value has been stored, it can be printed, manipulated, compared in IF statements, etc. Below will cover how to store a returned value.<br><br>
</syntaxhighlight>
:#Notice that this syntax looks just the call to the input() function which you've used in the last lab:<source lang="python">
 
This probably seems even less useful than the previous useless function, but again: the point is to show you the basic building blocks. Once you understand what you have to work with: you can start thinking of writing useful code.
 
One major difference between a function '''returning a value''' and simply '''printing a value''' is that '''returned''' values can be stored in variables used in the program (that called the function) for later use. Once the returned value has been stored, it can be printed, manipulated, compared in IF statements, etc.  
 
* Store the value returned by return_text_value() in a variable named '''text''':<syntaxhighlight lang="python">
text = return_text_value()
text = return_text_value()
</source>
</syntaxhighlight>
:#Now the returned text from the function has been stored in the variable "'''text'''". It can be used like any string value now.<source lang="python">
 
* Notice that this syntax looks just the call to the input() function which you've used in the last lab.
* Now that the returned text from the function has been stored in the variable "'''text'''", it can be used like any string value. For example you can print it:<syntaxhighlight lang="python">
print(text)
print(text)
</source>
</syntaxhighlight>


'''Functions and Numbers (Integers)'''
== Simple functions with integers ==


: You will now learn how to define and run functions that will return '''integer data''' when a function is called. In this section, you will define a function that will be returning integer values instead of text. There is not a big difference, but when returning number values, care needs to be taken if you try combining it with a string!
In this section, you will define a function that will be returning integer values instead of text. There is not a big difference, but you do have to understand that the "data type" concept still applies.


:'''Perform the Following steps:'''
* Define the return_number_value() function:<syntaxhighlight lang="python">
 
:#Define the return_number_value() function:<source lang="python">
def return_number_value():
def return_number_value():
     num1 = 10
     num1 = 10
Line 65: Line 78:
     num3 = num1 + num2
     num3 = num1 + num2
     return num3
     return num3
 
</syntaxhighlight>
</source>
* And call it:<syntaxhighlight lang="python">
:#And call it:<source lang="python">
number = return_number_value()
number = return_number_value()
print(number)
print(number)
print(number + 5)
print(number + 5)
print(return_number_value() + 10)
print(return_number_value() + 10)
</source> What do you notice?<br><br>  
</syntaxhighlight>
:#Now, display both strings and numbers:<source lang="python">
 
At this point that code should be pretty self-explanatory.
 
* Now, display both strings and numbers:<syntaxhighlight lang="python">
number = return_number_value()
number = return_number_value()
print('my number is ' + number)
print('my number is ' + number)
</source> What do you notice? You should notice a warning message. This occurs because the returning value is a '''number''' and NOT a '''string'''! Combining numbers and strings in a statement (such as '''print()''') can cause errors. The error message should appear similar to the one displayed below: <source>
</syntaxhighlight>  
Traceback (most recent call last):
 
  File "test.py", line 2, in <module>
Your code will execute until the line where you're asking to concatenate a stirng with a number, at which point you get the error you have seen before.
    print('my number is ' + number)
 
TypeError: cannot concatenate 'str' and 'int' objects
* Change your code to use the '''str()''' function in order to convert the returned number into a string:<syntaxhighlight lang="python">
</source>
:#If a number needs to be combined with a string, use the '''str()''' predefined function that was discussed in a previous lab in order to convert the returned number into a string:<source lang="python">
number = return_number_value()
number = return_number_value()
print('my number is ', number)
print('my number is ', number)
print('my number is ' + str(number))
print('my number is ' + str(number))
print('my number is ' + str(return_number_value()))
print('my number is ' + str(return_number_value()))
</source>
</syntaxhighlight>
 
== PART 2 - Creating a Python Script with Functions and Importing Functions ==
 
'''Creating a Python Script'''
 
:Now it's time to create a Python script that uses two functions. One function returns a string value to greet the user, where the other function returns the result of adding two values (stored in variables within the function).
 
:'''Perform the following Instructions:'''


:#Create a new script '''~/ops435/lab3/lab3a.py'''
== Importing functions ==


:::'''Input / Output Requirements'''
* Create a new script '''~/ops435/lab3/lab3a.py'''
 
* The script should have a '''Shebang line'''
:::*The script should have a '''Shebang line'''
* Below the '''Shebang line''', add an '''empty line''' followed by a comment stating: '''# return_text_value() function'''
:::*Below the '''Shebang line''', add an '''empty line''' followed by a comment stating: '''# return_text_value() function'''
* Add an '''empty line''' followed by the '''return_text_value()''' function '''definition''' that you previously entered in your test program.
:::*Add an '''empty line''' followed by the '''return_text_value()''' function '''definition''' that you previously entered in the shell.
* Add another '''empty line''' followed by a comment stating: '''# return_number_value() function'''
:::*Add another '''empty line''' followed by a comment stating: '''# return_number_value() function'''
* Add another '''empty line''' following by the '''return_number_value()''' function '''definition''' that you previously entered in your test program.
:::*Add another '''empty line''' following by the '''return_number_value()''' function '''definition''' that you previously entered in the shell.
* Add a '''couple of empty lines''', following by a comment stating: '''# Main Program'''
:::*Add a '''couple of empty lines''', following by a comment stating: '''# Main Program'''
* Add another '''couple of empty lines''', followed by the statements displayed below:<syntaxhighlight lang="python">
:::*Add another '''couple of empty lines''', followed by the statements displayed below:<source lang="python">
if __name__ == '__main__':
if __name__ == '__main__':
     print('python code')
     print('python code')
Line 114: Line 118:
     number = return_number_value()
     number = return_number_value()
     print(str(number))
     print(str(number))
</source>
</syntaxhighlight>
:Running your program you should have seen three lines being displayed: the text "python code", a greeting, and a result of a math calculation. The '''if''' statement in the code above is a special '''if''' statement needed to make sure that your "main" code only runs when you want it to. More on that later.


'''Importing Functions From other Python Scripts'''
Compared to other programming languages that's a backwards way of defining the starting point for your program, but that's how it's done in Python.


In order to use functions from other scripts, you use the '''import''' statement.<br><br>
Once your program gets complicated enough: you will split it into multiple files. In order to use functions from other files, you use the '''import''' statement.


:# Let's see what happens if we forget to import functions from your lab3a.py script prior to calling a function. Create a new python file and try to call the return_text_value() function:<source lang="python">
* Let's see what happens if we forget to import functions from your lab3a.py script prior to calling a function. Create a new python file test2.py and try to call the return_text_value() function:<syntaxhighlight lang="python">
text = lab3a.return_text_value()
text = lab3a.return_text_value()
</source>You should notice an error indicating '''"name 'lab3a' is not defined"'''. This error occurs since you failed to instruct python to '''import''' or "load existing defined functions from your lab3a.py script" to '''internal memory'''.<br><br>
</syntaxhighlight>
:# Modify your program like this:<source lang="python">
 
You should notice an error indicating '''"name 'lab3a' is not defined"'''. This error occurs since you failed to instruct python to '''import''' or "load existing defined functions from your lab3a.py program into RAM.
 
Modify your program like this:<syntaxhighlight lang="python">
import lab3a
import lab3a
text = lab3a.return_text_value()
text = lab3a.return_text_value()
print(text)
print(text)
lab3a.return_number_value()
lab3a.return_number_value()
</source> You should notice that all of the function calls should now work.
</syntaxhighlight>
:# Download the checking script and check your work. Enter the following commands from the bash shell.<source lang="bash">
 
All of the function calls should now work.
 
* Download the checking script and check your work. Enter the following commands from the bash shell.<syntaxhighlight lang="bash">
cd ~/ops435/lab3/
cd ~/ops435/lab3/
pwd #confirm that you are in the right directory
pwd # confirm that you are in the right directory
ls CheckLab3.py || wget https://raw.githubusercontent.com/Seneca-CDOT/ops435/master/LabCheckScripts/CheckLab3.py
ls CheckLab3.py || wget http://ops345.ca/ops445/CheckLab3.py
python3 ./CheckLab3.py -f -v lab3a
python3 ./CheckLab3.py -f -v lab3a
</source>
</syntaxhighlight>
:# Before proceeding, make certain that you identify any and all errors in lab3a.py. When the checking script tells you everything is OK before proceeding to the next step.
* Before proceeding, make certain that you identify any and all errors in lab3a.py. When the checking script tells you everything is OK before proceeding to the next step.
<br><br>
<br><br>


= INVESTIGATION 2: CREATING FUNCTIONS WITH ARGUMENTS AND RETURN VALUES =
== Providing Functions With Arguments ==


== PART 1 - Providing Functions With Arguments ==
Functions can receive '''arguments''' - one or more pieces of data. In this section, you will learn how to define functions that accept arguments and call thos functions.


:Functions can receive '''arguments''' - data to be used for processing. In this section, you will learn how to define functions that accept arguments and learn how to call functions with arguments (such as mathematical operations or testing conditions, which is useful for error-checking).
=== Receiving arguments in a function ===


'''Passing up Single and Multiple Arguments to a Function'''
When passing arguments to functions, you put data such as '''strings''' and '''numbers''' within brackets immediately following the function name.


:'''Perform the Following Steps:'''
If a function accepts arguments, then those arguments must be declared (using variable names) when the function is declared. Those declared variable names can then used within the function the same way any other declared variables are used.
:#Create a new Python file for testing.
 
:#When passing arguments to functions, you put data such as '''strings''', '''numbers''', or '''variable names''' within brackets immediately following the function name.<br><br>'''NOTE:''' If a function accepts arguments, then those arguments must be declared (using variable names) when the function is declared. Those declared variable names are then used within the function for processing. Also, when you call a function with arguments, the number of arguments passed up to the function must match the number of arguments that were specified in the function declaration.<br><br>
In this lab: when you call one of your functions with arguments, the number of arguments passed to the function must match the number of arguments that were specified in the function declaration.
:#Define a function called '''square()''':<source lang="python">
 
* Create a new Python file for testing.
* Define a function called '''square()''':<syntaxhighlight lang="python">
def square(number):
def square(number):
     return number ** 2
     return number ** 2
</source>'''FYI:'''You may have learned that you multiple a number by itself in order to "square" the number. In python, the '''**''' operator will raise the operand on the left to the power of the operand on the right.<br><br>When calling functions with multiple arguments, the arguments are separated by '''commas'''. See what happens if you provide strings, strings without using quotes, or numbers with decimals in the following examples.
</syntaxhighlight>
:#Test your '''square()''' function:<source lang="python">
 
{{Admon/tip|Power of two|Your probably know that you multiple a number by itself in order to "square" the number (i.e. raise it to the power of two). In python, the '''**''' operator will raise the operand on the left to the power of the operand on the right.}}
 
* Test your '''square()''' function:<syntaxhighlight lang="python">
square(5)
square(5)
square(10)
square(10)
Line 160: Line 174:
square(square(2))
square(square(2))
square('2')
square('2')
</source>Notice that nothing is printed, you need to print the values the functions return to see what they are.
</syntaxhighlight>
:#The last function call should produce an '''error message'''. This is caused by sending a '''string''' instead of a number that is processed by the function. We could use the int() function to convert any value passed in as a string by mistake to an integer number.<br><br>
 
:#Declare the function '''sum_numbers()''':<source lang="python">
Notice that nothing is printed, you need to print the values the functions return to see what they are.
 
The last function call should produce an '''error message'''. This is caused by sending a '''string''' instead of a number that is expected by the function. We could use the int() function to convert any value passed in as a string by mistake to an integer number.
 
* Declare the function '''sum_numbers()''' which will receive two arguments:<syntaxhighlight lang="python">
def sum_numbers(number1, number2):
def sum_numbers(number1, number2):
     return int(number1) + int(number2)
     return int(number1) + int(number2)
</source>
</syntaxhighlight>
:#Call that function to see what happens:<source lang="python">
* Call that function to see what happens:<syntaxhighlight lang="python">
sum_numbers(5, 10)
sum_numbers(5, 10)
sum_numbers(50, 100)
sum_numbers(50, 100)
</source>
</syntaxhighlight>
:#You can also do what looks like calling a function within another function, but it's actually just calling sum_numbers() first, then calling square() with the return from sum_numbers as an argument:<source lang="python">
* You can also do what looks like calling a function within another function, but it's actually just calling sum_numbers() first, then calling square() with the return from sum_numbers as an argument:<syntaxhighlight lang="python">
square(sum_numbers(5, 5))
square(sum_numbers(5, 5))
</source>'''NOTE:''' Running functions with multiple arguments is the same. When call a function as an argument of another function, the '''inner-most function will run first''', and the return the value from that will be used as the argument for the '''outer function'''. In the example below, '''sum_numbers(5, 5)''' will return '''10''', thus providing that result to be  square with that value '''square(10)'''.<br><br>
</syntaxhighlight>


'''Practice Creating a Function that Accepts Arguments and Returns a Value'''
When you call a function as an argument to another function, the '''inner-most function will run first''', and the return the value from that will be used as the argument for the '''outer function'''. In this example '''sum_numbers(5, 5)''' will return '''10''', thus providing that result to be  square with that value '''square(10)'''.


:It is time to practice creating a shell script that uses a function that accepts arguments, and returns a value.
=== Create a function that accepts arguments and returns a value ===


:'''Perform the Following Instructions:'''
* Create a new program '''~/ops435/lab3/lab3b.py'''. Refer to the '''Python Program Template''', the '''Sample Run''' and the '''Sample Imports''' sections.
:#Create a new script '''~/ops435/lab3/lab3b.py'''. Refer to the '''Python Script template''' and the '''Additional Requirements''' sections when creating your Python script. Refer to Sample Run and Sample Imports displayed below for exact prompt and output


:::'''Python Script Template'''
'''Python Program Template'''


:::<source lang="python">#!/usr/bin/env python3
<syntaxhighlight lang="python">
#!/usr/bin/env python3


def sum_numbers(number1, number2):
def sum_numbers(number1, number2):
Line 201: Line 218:
     print(subtract_numbers(10, 5))
     print(subtract_numbers(10, 5))
     print(multiply_numbers(10, 5))
     print(multiply_numbers(10, 5))
</syntaxhighlight>


</source>
'''Sample Run:'''<syntaxhighlight lang="bash">
 
::'''Additional Requirements'''
 
::*All functions should accept two arguments
::*All functions should return an integer
::*The script should contain no errors
 
::'''Sample Run:'''<source lang="python">
./lab3b.py
./lab3b.py
15
15
5
5
50
50
</source>
</syntaxhighlight>
::'''Other examples:'''<source lang="python">
 
'''Other examples:'''<syntaxhighlight lang="python">
import lab3b
import lab3b


Line 231: Line 242:
lab3b.multiply_numbers(10, 2)
lab3b.multiply_numbers(10, 2)
# Will return 20
# Will return 20
</source>
</syntaxhighlight>


::2. Download the checking script and check your work. Enter the following commands from the bash shell.<source lang="bash">
* Download the checking script and check your work:<syntaxhighlight lang="bash">
cd ~/ops435/lab3/
cd ~/ops435/lab3/
pwd #confirm that you are in the right directory
pwd # confirm that you are in the right directory
ls CheckLab3.py || wget https://raw.githubusercontent.com/Seneca-CDOT/ops435/master/LabCheckScripts/CheckLab3.py
ls CheckLab3.py || wget http://ops345.ca/ops445/CheckLab3.py
python3 ./CheckLab3.py -f -v lab3b
python3 ./CheckLab3.py -f -v lab3b
</source>
</syntaxhighlight>


::3. Before proceeding, make certain that you identify any and all errors in lab3b.py. When the checking script tells you everything is OK - proceed to the next step.
* Before proceeding, make certain that you identify any and all errors in lab3b.py. When the checking script tells you everything is OK - proceed to the next step.


'''Passing up Multiple Arguments and Using Conditional Statements'''
=== A smarter function ===


:You will now create a more complex function that will not only pass arguments, but also include logic to control the flow of the function, and affect how your Python script will be run. You will create a function that uses an '''if/elif/else''' statement.
You will now create a more complex function that will not only receive arguments, but also include logic to control the flow of the function, and affect the result the function will produce. You will create a function that uses an '''if/elif/else''' statement.


:'''Perform the Following Steps:'''
* Use a temporary Python file to define the following function:<syntaxhighlight lang="python">
:#Use a temporary Python file to define the following function:<source lang="python">
def describe_temperature(temp):
def describe_temperature(temp):
     if temp > 30:
     if temp > 30:
Line 256: Line 266:
         return 'perfect'
         return 'perfect'
     return 'ok'       
     return 'ok'       
</source>The final '''return "ok"''' will only take place if a previous return has not taken place before it. Once return has been used in a function, the function immediately exits and returns the value.
</syntaxhighlight>
:#Call describe_temperature like this to confirm the results:<source>
 
The final '''return "ok"''' will only take place if a previous return has not taken place before it. Once return has been used in a function, the function immediately exits and returns the value.
 
* Call describe_temperature() like this to confirm the results:<syntaxhighlight lang="python">
print(describe_temperature(50))
print(describe_temperature(50))
# Will return 'hot'
# Should print 'hot'
print(describe_temperature(20))
print(describe_temperature(20))
# Will return 'perfect'
# Should print 'perfect'
print(describe_temperature(-50))
print(describe_temperature(-50))
# Will return 'cold'
# Should print 'cold'
print(describe_temperature(25))
print(describe_temperature(25))
# Will return 'ok'
# Should print 'ok'
print(describe_temperature(10))
print(describe_temperature(10))
# Will return 'ok'
# Should print 'ok'
</source>
</syntaxhighlight>


'''Create a Python Script Receiving Multiple Arguments'''
* Create the '''~/ops435/lab3/lab3c.py''' program. The purpose of the program is to have a single function that can perform addition, subtraction, or multiplication on a pair of numbers. But the function will allow us to choose exatly what operation we are performing on it when we call it. If the operate function does NOT understand the operator given, it should return an error message (e.g. calling the function to 'divide' two numbers).
 
* Use this template to get started:<syntaxhighlight lang="python">
:'''Perform the Following Instructions:'''
:#Create the '''~/ops435/lab3/lab3c.py''' script. The purpose of the script is to have a single function that can perform addition, subtraction, or multiplication on a pair of numbers. But the function will allow us to choose exatly what operation we are performing on it when we call it. If the operate function does NOT understand the operator given, it should return an error message (e.g. calling the function to 'divide' two numbers).
:#Use this template to get started:<source lang="python">
#!/usr/bin/env python3
#!/usr/bin/env python3


Line 285: Line 295:
     print(operate(10, 5, 'multiply'))
     print(operate(10, 5, 'multiply'))
     print(operate(10, 5, 'divide'))
     print(operate(10, 5, 'divide'))
</source>
</syntaxhighlight>
:::*The operate() function should use '''conditional''' statements<br> &nbsp; '''FYI:''' Remember that you MUST consistently '''indent ALL code''' for within each section (or test).
:::*The operate() function should accept '''three arguments'''.
:::*The operate() function should '''return''' the result.
:::*The operate() function should '''return''' an error message if the operation is unknown<br> &nbsp; '''FYI:''' Use single quotes or double-quotes to pass a string value.
:::*The script should contain show the exact output as the sample.
:::*The script should contain no errors.
:::*As an extra exercise, try to write your function with only one return statement.


:::'''Sample Run 1:'''<source>
* Complete the function considering the following requirements:
# The operate() function should use '''conditional''' statements.
# The operate() function should accept '''three arguments'''.
# The operate() function should '''return''' the result.
# The operate() function should '''return''' an error message (a string) if the operation is unknown.
# The program should contain show the exact output as the sample.
# As an extra exercise, try to write your function with only one return statement.
 
'''Sample Run 1:'''<syntaxhighlight lang="bash">
./lab3c.py
./lab3c.py
15
15
Line 300: Line 311:
50
50
Error: function operator can be "add", "subtract", or "multiply"
Error: function operator can be "add", "subtract", or "multiply"
</source>
</syntaxhighlight>


:::'''Sample Run 2 (using import from another Python file):'''<source>
'''Sample Run 2 (using import from another Python file):'''<syntaxhighlight lang="bash">
import lab3c
import lab3c
lab3c.operate(10, 20, 'add')
lab3c.operate(10, 20, 'add')
Line 320: Line 331:
lab3c.operate(100, 5, 'power')
lab3c.operate(100, 5, 'power')
# Will return Error: function operator can be "add", "subtract", or "multiply"
# Will return Error: function operator can be "add", "subtract", or "multiply"
</source>
</syntaxhighlight>
:::3. Download the checking script and check your work. Enter the following commands from the bash shell.<source lang="bash">
 
* Download the checking script and check your work. Enter the following commands from the bash shell.<syntaxhighlight lang="bash">
cd ~/ops435/lab3/
cd ~/ops435/lab3/
pwd #confirm that you are in the right directory
pwd #confirm that you are in the right directory
ls CheckLab3.py || wget https://raw.githubusercontent.com/Seneca-CDOT/ops435/master/LabCheckScripts/CheckLab3.py
ls CheckLab3.py || wget http://ops345.ca/ops445/CheckLab3.py
python3 ./CheckLab3.py -f -v lab3c
python3 ./CheckLab3.py -f -v lab3c
</source>
</syntaxhighlight>
:::4. Before proceeding, make certain that you identify any and all errors in lab3c.py. When the checking script tells you everything is OK - proceed to the next step.
 
<br><br>
* Before proceeding, make certain that you identify any and all errors in lab3c.py. When the checking script tells you everything is OK - proceed to the next step.
 
= Running System Commands =


== PART 2 - Running System Commands with Subprocess ==
You to run operating system commands from your Python program. There are several different ways to issue operating system commands, you will learn two of them.
:The remainder of this investigation will allow you to run operating system commands via your Python script. Although there are different ways in which to issue operating system commands, you will learn two of them.


'''Perform the Following Steps:'''
In some ways calling a program is very similar to calling a function, but the underlying mechanism for doing that is completely different, so don't expect it to work exactly the same way.


:#Create a new python file for testing.
* Create a new python file for testing.
:#Import the '''''os''''' module in your python file.
* Import the '''''os''''' module in your python file.
:#You can issue operating system commands by using the '''system()''' function. Try it:<source lang="python">
* You can issue operating system commands by using the '''system()''' function. Try it:<syntaxhighlight lang="python">
os.system('ls')
os.system('ls')
os.system('whoami')
os.system('whoami')
os.system('ifconfig')
os.system('ifconfig')
</source>Notice that the output from the programs is printed in your script. Consider that may not always be what you want.<br><br>
</syntaxhighlight>
:#Try this also:<source lang="python">
Notice that the output from the programs is printed in your program. Consider that may not always be what you want.
* Try this also:<syntaxhighlight lang="python">
os.system('ipconfig')
os.system('ipconfig')
</source>You should notice an error message: ''''ipconfig: command not found''''. That error occurs since that command was an MS Windows command, and our current platform is Linux.<br><br>It is not always a good idea to run system commands in Python, this makes your Python code less portable and makes it require a specific operating system or a system that has those commands available. You should think about that when you decide whether you should or should not use a system command to accomplish some task or stick to pure Python code only.<br><br>As you may recall from lab2, you issued '''import sys''' to import special variables from the system. You can import a subprocess in order to run common non OS specific commands securely.<br><br>
</syntaxhighlight>
:#Import the subprocess module in your python file.
You should notice an error message: ''''ipconfig: command not found''''. That error occurs since that command was a Windows command, and our current platform is Linux. If you're really paying attention: you will notice that the error is a shell error, not a python error.
:#There are many features available as part of the subprocess module, we are interested in "'''Popen'''". This method subprocess.Popen() can be used to run system commands as a child process to the Python script. The code below output will create a new child process, in Python we can control this through the new Python object we just created, "'''p'''". "'''p'''" now has a collection of methods(functions that are apart of a object) available.<br><br>
 
:#To demonstrate, issue the following:<source lang="python">
It is not always a good idea to run system commands in Python, this makes your Python code less portable and makes it require a specific operating system or a system that has those commands available. You should think about that when you decide whether you should or should not use a system command to accomplish some task or stick to pure Python code only.
 
Another way to run commands is using the subprocess module.
 
* Import the subprocess module in your python file.
* There are many features available as part of the subprocess module, we are interested in "'''Popen'''".  
* This subprocess.Popen() function can be used to run system commands as a child process to the Python script. The code below output will create a new child process, in Python we can control this through the new Python object we just created, "'''p'''". "'''p'''" will have a collection of methods(functions that are apart of a object) available.
* To demonstrate, try the following:<syntaxhighlight lang="python">
p = subprocess.Popen(['date'], stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
p = subprocess.Popen(['date'], stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
</source>This function call and the following step is full of details we haven't yet talked about which is why it may look a little scary. By the time we're finished with the course - you will be able to look at code like this and not be intimidated. If you're curious and want to look ahead - you can find the definition for the [https://docs.python.org/3/library/subprocess.html#subprocess.Popen Popen function in the Python reference manual].
</syntaxhighlight>
:#This next step is going to communicate with the process and get the retrieve it's output (stdout).<source>
 
This function call and the following step is full of details we haven't yet talked about which is why it may look a little scary. By the time we're finished with the course - you will be able to look at code like this and not be intimidated. If you're curious and want to look ahead - you can find the definition for the [https://docs.python.org/3/library/subprocess.html#subprocess.Popen Popen function in the Python reference manual].
 
* Communicate with the process and retrieve its output (stdout).<syntaxhighlight lang="python">
output = p.communicate()
output = p.communicate()
print(output)
print(output)
Line 358: Line 382:
stdout = output[0].decode('utf-8').strip()
stdout = output[0].decode('utf-8').strip()
print(stdout)
print(stdout)
</source>
</syntaxhighlight>
:# Sometimes you will be able to use purely python code to get your job done, but often you will need to call existing system commands. It's important to learn how to call them and how to interact with those external processes.


'''Practice Running System Commands From Python'''
Sometimes you will be able to use purely python code to get your job done, but often you will need to call existing system commands. It's important to learn how to call them and how to interact with those external processes.
:'''Perform the Following Instructions:'''
 
<ol>
* Create the "'''~/ops435/lab3/lab3d.py'''" program. Create a Python function that can return the linux system's root filesystem's free space.
<li>Create the "'''~/ops435/lab3/lab3d.py'''" script. The purpose of this script is to create a Python function that can return the linux system's root directory free space.
* The program should '''import the correct module'''
:*The script should '''import the correct module'''
* The program should use the linux command: '''<nowiki>df -h | grep '/$' | awk '{print $4}'</nowiki>'''  
:*The script should use the linux command: '''<nowiki>df -h | grep '/$' | awk '{print $4}'</nowiki>'''  
* The program should contain the function called: '''free_space()'''
:*The script should contain the function called: '''free_space()'''
* The function '''free_space()''' should return a string which is in '''utf-8''' and has no newline in the end.
:*The function '''free_space()''' should return a string which is in '''utf-8''' and has '''newline characters strip'''
* Your output may be different, the free/available disk space on different computers is rarely the same.
:*'''Note:''' your output may be completely different, the free/available disk space on every computers root directory may be different.
 
:'''Sample Run 1:''' <source>
 
'''Sample Run 1:''' <syntaxhighlight lang="bash">
./lab3d.py
./lab3d.py
9.6G
9.6G
</source>
</syntaxhighlight>
:'''Sample Run 2 (using import from another Python file):'''<source>
 
'''Sample Run 2 (using import from another Python file):'''<syntaxhighlight lang="python">
import lab3d
import lab3d
lab3d.free_space()
lab3d.free_space()
# Will return 9.6G
# Will return 9.6G
</source></li>
</syntaxhighlight>
<li>Download the checking script and check your work. Enter the following commands from the bash shell.<source lang="bash">
 
* Download the checking script and check your work:<syntaxhighlight lang="bash">
cd ~/ops435/lab3/
cd ~/ops435/lab3/
pwd #confirm that you are in the right directory
pwd #confirm that you are in the right directory
ls CheckLab3.py || wget https://raw.githubusercontent.com/Seneca-CDOT/ops435/master/LabCheckScripts/CheckLab3.py
ls CheckLab3.py || wget http://ops345.ca/ops445/CheckLab3.py
python3 ./CheckLab3.py -f -v lab3d
python3 ./CheckLab3.py -f -v lab3d
</source></li>
</syntaxhighlight>
<li>Before proceeding, make certain that you identify any and all errors in lab3d.py. When the checking script tells you everything is OK - proceed to the next step.</li>
 
</ol>
* Before proceeding, make certain that you identify any and all errors in lab3d.py. When the checking script tells you everything is OK - proceed to the next step.
 
= Lists =
 
A '''List''' is a non-trivial data-type in Python. You define a list using a series of '''comma separated values found between square brackets'''. Values in a list can be anything: '''strings''', '''integers''', '''objects''', even '''other lists'''.
 
It is important to realise that although lists may appear very similar to arrays in other languages, they are different in a number of aspects including the fact that they don't have a fixed size.


= INVESTIGATION 3: USING LISTS =
== Navigating items in lists ==


:'''Lists''' are one of the most powerful '''data-types''' in Python. A list is a series of '''comma separated values found between square brackets'''. Values in a list can be anything: '''strings''', '''integers''', '''objects''', even '''other lists'''. In this section, you will introduce lists and how to use them effectively, you will further user lists in later labs. It is important to realise that although lists may appear very similar to arrays in other languages, they are different in a number of aspects including the fact that they don't have a fixed size.
* Create a new Python file for testing things in this section.
* Create three lists with different values: list1 contains only '''integers''', list2 contains only '''strings''', list3 contains a combination of both '''integers and strings''' <syntaxhighlight lang="python">
list1 = [1, 2, 3, 4, 5, 6, 7, 8, 9]
list2 = ['uli101', 'ops235', 'ops335', 'ops435', 'ops535', 'ops635']
list3 = ['uli101', 1, 'ops235', 2, 'ops335', 3, 'ops435', 4, 'ops535', 5, 'ops635', 6]
</syntaxhighlight>


== PART 1 - Navigating Items in Lists ==
The simplest way to access individual '''elements''' in a list is using the list '''index'''.


:'''Perform the Following Steps'''
The index is a number starting from 0 to ('''number_of_items - 1'''). The index of the first element is '''0'''.<br><br>


:#Create a new Python file for testing things in this section.
* Inspect specified elements in your lists:<syntaxhighlight lang="python">
:#Create a few lists with different values: list1 contains only '''integers''', list2 contains only '''strings''', list3 contains a combination of both '''integers and strings'''
:#<source lang="python">
list1 = [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
list2 = [ 'uli101', 'ops235', 'ops335', 'ops435', 'ops535', 'ops635' ]
list3 = [ 'uli101', 1, 'ops235', 2, 'ops335', 3, 'ops435', 4, 'ops535', 5, 'ops635', 6 ]
</source>The best way to access individual '''elements''' in a list is using the list '''index'''.<br>The index is a number starting from 0 to ('''number_of_items - 1'''), the list index starts counting at '''0'''.<br><br>
:#Inspect specified elements in your lists:<source lang="python">
print(list1[0])  # First element in list1
print(list1[0])  # First element in list1
print(list2[1])  # Second element in list2
print(list2[1])  # Second element in list2
print(list3[-1]) # Last element in list3
print(list3[-1]) # Last element in list3
</source>
</syntaxhighlight>
:#You can also retrieve ranges of items from a list (these are called slices): <source lang="python">
 
* You can also retrieve ranges of items from a list (these are called slices): <syntaxhighlight lang="python">
print(list1[0:5]) # Starting with index 0 and stopping before index 5
print(list1[0:5]) # Starting with index 0 and stopping before index 5
print(list2[2:4]) # Starting with index 2 and stopping before index 4
print(list2[2:4]) # Starting with index 2 and stopping before index 4
print(list3[3:])  # Starting with index 3 and going to the end
print(list3[3:])  # Starting with index 3 and going to the end
</source>
</syntaxhighlight>


'''Practice Using Functions and Using the List Index'''
* Create a Python program called: '''~/ops435/lab3/lab3e.py'''
 
The program will have a number of functions which output various parts of a list. Each function will return either a single item from the list OR will create a new list and return the entire new list.
:'''Perform the Following Instructions'''
* Start with this template:<syntaxhighlight lang="python">
 
:#Create a Python script called: '''~/ops435/lab3/lab3e.py'''<br>The purpose of this script is to have a number of functions that output a different data storage in various elements of a list. Each function will return either a single item from the list OR will create a new list and return the entire new list.<br><br>
:#The template function names and the special if statement:<source lang="python">
#!/usr/bin/env python3
#!/usr/bin/env python3


Line 447: Line 475:
     print(give_first_and_last_item())
     print(give_first_and_last_item())
     print(give_second_and_third_item())
     print(give_second_and_third_item())
</source>
</syntaxhighlight>


:::'''Additional Requirements'''
* Here's what you need to do:
# The script should declare a list called '''my_list''' created BEFORE any function definition
# The list called '''my_list''' should have the values: '''100''', '''200''', '''300''', and '''"six hundred"'''
# The script should '''implement''' the empty functions - i.e. you have to fill in the bodies for these functions


:::*The script should declare a list called '''my_list''' created BEFORE any function definition
'''Sample Run 1:'''<syntaxhighlight lang="bash">
:::*The list called '''my_list''' should have the values: '''100''', '''200''', '''300''', and ''''six hundred''''
:::*The script should '''implement''' the empty functions - i.e. you have to fill in the bodies for these functions
 
:::'''Sample Run 1:'''<source>
./ lab3e.py
./ lab3e.py
[100, 200, 300, 'six hundred']
[100, 200, 300, 'six hundred']
Line 461: Line 488:
[100, 'six hundred']
[100, 'six hundred']
[200, 300]
[200, 300]
</source>
</syntaxhighlight>
:::'''Sample Run 2 (with import from another script):'''<source>
'''Sample Run 2 (with import from another script):'''<syntaxhighlight lang="python">
import lab3e
import lab3e
lab3e.give_list()
lab3e.give_list()
Line 472: Line 499:
lab3e.give_second_and_third_item()
lab3e.give_second_and_third_item()
# Will print [200, 300]
# Will print [200, 300]
</source>
</syntaxhighlight>
:::3. Download the checking script and check your work. Enter the following commands from the bash shell.<source>
* Download the checking script and check your work:<syntaxhighlight lang="bash">
cd ~/ops435/lab3/
cd ~/ops435/lab3/
pwd #confirm that you are in the right directory
pwd # confirm that you are in the right directory
ls CheckLab3.py || wget https://raw.githubusercontent.com/Seneca-CDOT/ops435/master/LabCheckScripts/CheckLab3.py
ls CheckLab3.py || wget http://ops345.ca/ops445/CheckLab3.py
python3 ./CheckLab3.py -f -v lab3e
python3 ./CheckLab3.py -f -v lab3e
</source>
</syntaxhighlight>
:::4. Before proceeding, make certain that you identify any and all errors in lab3e.py. When the checking script tells you everything is OK - proceed to the next step.


== PART 2 - Manipulating Items in Lists ==
* Before proceeding, make certain that you identify any and all errors in lab3e.py. When the checking script tells you everything is OK - proceed to the next step.


:There are a number of ways to obtain information about lists as well as change the data that is contained within a list. In this section, you will learn how to manipulate lists.
== Manipulating items in lists ==


:'''Perform the Following Steps:'''
There is a number of ways to obtain information about lists as well as change the data that is contained within a list. In this section, you will learn how to manipulate lists.


:#Let's perform a simple change to a list element. Try the following code:<source lang="python">
* Let's perform a simple change to a list element. Try the following code in a temporary python file:<syntaxhighlight lang="python">
courses = [ 'uli101', 'ops235', 'ops335', 'ops435', 'ops535', 'ops635' ]
courses = ['uli101', 'ops235', 'ops335', 'ops435', 'ops535', 'ops635']
print(courses[0])
print(courses[0])
courses[0] = 'eac150'
courses[0] = 'eac150'
print(courses[0])
print(courses[0])
print(courses)
print(courses)
</source>
</syntaxhighlight>
:#Below are some examples of using built-in functions to '''manipulate''' lists. Take your time to see how each function can be a useful tool for making changes to existing lists:<source lang="python">
 
* Below are some examples of using built-in functions to '''manipulate''' lists. Take your time to see how each function can be a useful tool for making changes to existing lists:<syntaxhighlight lang="python">
courses.append('ops235')    # Add a new item to the end of the list
courses.append('ops235')    # Add a new item to the end of the list
print(courses)
print(courses)
Line 508: Line 535:
print(courses)
print(courses)
print(sorted_courses)
print(sorted_courses)
</syntaxhighlight>


</source>
* In addition to using functions to manipulate lists, there are functions that are useful to provide '''information''' regarding the list such as number of elements in a list, the smallest value and largest value in a list:<syntaxhighlight lang="python">
:#In addition to using functions to manipulate lists, there are functions that are useful to provide '''information''' regarding the list such as number of elements in a list, the smallest value and largest value in a list:<source lang="python">
list_of_numbers = [ 1, 5, 2, 6, 8, 5, 10, 2 ]
list_of_numbers = [ 1, 5, 2, 6, 8, 5, 10, 2 ]
length_of_list = len(list_of_numbers)    # Returns the length of the list
length_of_list = len(list_of_numbers)    # Returns the length of the list
Line 516: Line 543:
largest_in_list = max(list_of_numbers)  # Returns the largest value in the list
largest_in_list = max(list_of_numbers)  # Returns the largest value in the list


# Notice how the long line below is wrapped to fit on one screen:
# Notice how the long line below is wrapped to fit on one editor screen, so you don't need to scroll to read it:
print("List length is " + str(length_of_list) +  
print("List length is " + str(length_of_list) +  
       ", smallest element in the list is " + str(smallest_in_list) +
       ", smallest element in the list is " + str(smallest_in_list) +
       ", largest element in the list is " + str(largest_in_list))
       ", largest element in the list is " + str(largest_in_list))
</source>
</syntaxhighlight>


== PART 3 - Iterating Over Lists ==
== Iterating over a list using the for loop ==


:This last section demonstrates an extremely useful for lists: the ability to quickly '''loop through every value in the list'''. '''For loops''' have a set number of times they loop. The '''for''' loop will execute all indented code for each item (element) in the list.
This last section demonstrates a quick and easy way to '''loop through every value in the list'''. '''For loops''' have a set number of times they loop. The '''for''' loop will execute all indented code for each item (element) in the list.


:'''Perform the Following Steps'''
Other programming languages that have a loop such as this: it is usually called a "foreach" loop.


::The following '''for''' loop will store the value of each element from list_of_numbers within a variable named '''item''' and run code indented below the loop for each item.<br><br>
The following '''for''' loop's body will execute as many times as there are elements in the list_of_numbers. For each element: it will store its value in a variable named '''item'''; and run code indented below.
:#Run this from a temporary Python file:<source lang="python">
 
list_of_numbers = [ 1, 5, 2, 6, 8, 5, 10, 2 ]
* Create a temporary Python file with these contents and run it:<syntaxhighlight lang="python">
list_of_numbers = [1, 5, 2, 6, 8, 5, 10, 2]
for item in list_of_numbers:
for item in list_of_numbers:
     print(item)
     print(item)
</source>
</syntaxhighlight>
:#As you can see: instead of writing eight function calls for each element of the list, we can call the function in a loop. And we won't have to rewrite code if the length of the list changes.<br><br>
 
:#Run the following code:<source lang="python">
* As you can see: instead of writing eight function calls for each element of the list, we can call the print() function in a loop. And we won't have to rewrite code if the length of the list changes.
list_of_numbers = [ 1, 5, 2, 6, 8, 5, 10, 2 ]
* Run the following code:<syntaxhighlight lang="python">
list_of_numbers = [1, 5, 2, 6, 8, 5, 10, 2]


def square(num):
def square(num):
Line 543: Line 572:
for value in list_of_numbers:
for value in list_of_numbers:
     print(square(value))
     print(square(value))
   
</syntaxhighlight>
</source>The code above only prints the squares and does not save them for future use. The next example uses a function that loops through list, squares the values, and also saves the squares in a new list.<br><br>
 
:#Run the following code:<source lang="python">
The code above only prints the squares and does not save them for future use. The next example uses a function that loops through list, squares the values, and also saves the squares in a new list.
list_of_numbers = [ 1, 5, 2, 6, 8, 5, 10, 2 ]
 
* Run the following code:<syntaxhighlight lang="python">
list_of_numbers = [1, 5, 2, 6, 8, 5, 10, 2]


# Squares each item in a list of numbers, returns new list with squared numbers
# Squares each item in a list of numbers, returns new list with squared numbers
Line 558: Line 589:
print(list_of_numbers)
print(list_of_numbers)
print(new_list_of_numbers)
print(new_list_of_numbers)
</source>The above is just one example of a quick use of for loops mixed with lists. But be careful when passing lists into functions. When you give a function a list as an argument, it is the actual list reference and NOT a copy. This means a function can change the list without making a new list. While you do have to be careful, this can also be useful. A function can modify any given list ''without'' have to return it.<br><br>
</syntaxhighlight>
:#To demonstrate, run the following code:<source lang="python">
 
The above is just one example of a quick use of for loops mixed with lists. But be careful when passing lists into functions. When you give a function a list as an argument, it is the actual list reference and NOT a copy. This means a function can change the list without making a new list. While you do have to be careful, this can also be useful. A function can modify any given list ''without'' having to return it.
 
* To demonstrate, run the following code:<syntaxhighlight lang="python">
list_of_numbers = [ 1, 5, 2, 6, 8, 5, 10, 2 ]
list_of_numbers = [ 1, 5, 2, 6, 8, 5, 10, 2 ]
def delete_numbers(numbers):
def delete_numbers(numbers):
Line 568: Line 602:
delete_numbers(list_of_numbers)
delete_numbers(list_of_numbers)
print(list_of_numbers)
print(list_of_numbers)
</source>
</syntaxhighlight>


'''Practice Functions, Lists, Loops'''
= Practice with Functions, Lists, and Loops =


:'''Perform the Following Instructions:'''
* Create the '''~/ops435/lab3/lab3f.py''' script. The purpose of this script is to use functions to modify items inside a list.
 
* Start with this:<syntaxhighlight lang="python">
:#Create the '''~/ops435/lab3/lab3f.py''' script. The purpose of this script is to use functions to modify items inside a list. <source lang="python">
#!/usr/bin/env python3
#!/usr/bin/env python3


Line 596: Line 629:
     remove_items_from_list(my_list, [1,5,6])
     remove_items_from_list(my_list, [1,5,6])
     print(my_list)
     print(my_list)
</source>
</syntaxhighlight>


'''Additional Requirements'''
* Complete the program following these requirements:
# The missing list  should have the values: '''1, 2, 3, 4, 5'''
# The program should have a function called '''add_item_to_list(ordered_list)'''. This function takes a single argument which is expected to be of type '''list'''. The function will retrieve the value of the last item in the list, and it will append a new value to that list so that the new value is one unit bigger than the previous last element.
# The add_item_to_list() function will modify the list it receives via the parameter, and will not return anything.
# The program should have a function called '''remove_items_from_list(ordered_list, items_to_remove)'''. This function takes two arguments: a list, and a second list of numbers to remove from the first list. For each item in the second list the function will check if that item exists in the first list, and if it exists: remove it.
# The remove_items_from_list() function will modify the ordered_list without returning any value.


:::*The missing list  should have the values: '''1, 2, 3, 4, 5'''
'''Sample Run 1:'''<syntaxhighlight lang="bash">
:::*The program should have a function called '''add_item_to_list(ordered_list)'''<dd><dl>This function takes a single argument which is a list name itself. It will then look at the value of the last existing item in the list, it will then append a new value that is one unit bigger (i.e. '''+1''' and modifying that same list without returning any value).</dl></dd>
:::*The script should have a function called '''remove_items_from_list(ordered_list, items_to_remove)'''<dd><dl>This function takes two arguments: a list, and a list of numbers to remove from the list. This function will then check if those items exist within that list, and if they exist, then they will be removed. This function will modify the list without returning any value.</dl></dd>
 
:::'''Sample Run 1:'''<source>
run lab3f.py
run lab3f.py
[1, 2, 3, 4, 5]
[1, 2, 3, 4, 5]
[1, 2, 3, 4, 5, 6, 7, 8]
[1, 2, 3, 4, 5, 6, 7, 8]
[2, 3, 4, 7, 8]
[2, 3, 4, 7, 8]
</source>
</syntaxhighlight>


:::'''Sample Run 2 (with import):'''<source>
'''Sample Run 2 (with import):'''<syntaxhighlight lang="python">
from lab3f import *                                                                                                                                                            print(my_list)
from lab3f import *                                                                                                                                                            print(my_list)
# Will print [1, 2, 3, 4, 5]
# Will print [1, 2, 3, 4, 5]
Line 622: Line 656:
print(my_list)
print(my_list)
# Will print [2, 3, 4, 7, 8]
# Will print [2, 3, 4, 7, 8]
</source>
</syntaxhighlight>
:::2. Download the checking script and check your work. Enter the following commands from the bash shell.<source>
 
* Download the checking script and check your work. Enter the following commands from the bash shell.<syntaxhighlight lang="bash">
cd ~/ops435/lab3/
cd ~/ops435/lab3/
pwd #confirm that you are in the right directory
pwd # confirm that you are in the right directory
ls CheckLab3.py || wget https://raw.githubusercontent.com/Seneca-CDOT/ops435/master/LabCheckScripts/CheckLab3.py
ls CheckLab3.py || wget http://ops345.ca/ops445/CheckLab3.py
python3 ./CheckLab3.py -f -v lab3f
python3 ./CheckLab3.py -f -v lab3f
</source>
</syntaxhighlight>
:::3. Before proceeding, make certain that you identify any and all errors in lab3f.py. When the checking script tells you everything is OK - proceed to the next step.
 
= LAB 3 SIGN OFF (SHOW INSTRUCTOR) =
[[Image:lab1_signoff.png|thumb|right|450px|Students should be prepared with '''all required commands (system information) displayed in a terminal (or multiple terminals) prior to calling the instructor for signoff'''.]]


* Before proceeding, make certain that you identify any and all errors in lab3f.py. When the checking script tells you everything is OK - proceed to the next step.


:'''Have Ready to Show Your Instructor:'''
= Submit evidence of your work =
 
Run the following command in a terminal:<syntaxhighlight lang="bash">
::<span style="color:green;font-size:1.5em;">&#x2713;</span> Output of: <code>./CheckLab3.py -f -v</code>
cd ~/ops435/lab3
::<span style="color:green;font-size:1.5em;">&#x2713;</span> Output of: <code>cat lab3a.py lab3b.py lab3c.py lab3d.py lab3e.py lab3f.py</code>
python3 ./CheckLab3.py -f
 
</syntaxhighlight>
:'''Be able to answer any questions about the lab to show that you understood it!'''
<br><br>
 
= LAB REVIEW =


:# What is the purpose of using functions in a Python script?
* The output of the lab check command must say '''OK'''.
:# Write Python code to define a function called '''greetings()''' that when called will greet the user by name and on the next line display the current date
* To show that you completed the lab, submit a screenshot of the terminal with that output.
:# Why is it useful for functions to accept '''arguments''' passed-up upon function execution?
:# What is the purpose of the '''import''' command? What can be the consequence if the import command is not used prior to running a function by name?
:# Write Python code to define a function called '''join()''' that excepts two arguments which will be be stored as the variables called '''word1''' and '''word2''' respectively during the execution of the function.
:# What is the command to return a value from a function?
:# What is the purpose of the '''system()''' function?
:# What is the purpose of a '''list'''?
:# Assume that the following list has been defined:  '''mylist = [ 'apple', 1, 'grape', 2, 'banana', 3, ]'''<br>Based on that, what will the following contain?<source lang="python">mylist[0]
mylist[3]
mylist[-1]
mylist[0:1]</source>
:# Assume that the following list has been defined: '''combined_list = [ [7, 5], ['x', 'y'], [ 5, 'f' ] ]'''<br>Based on that, what will the following contain?<source lang="python">
combined_list[0]
combined_list[1]
combined_list[1][0]
combined_list[2][0:2]</source>
:# Briefly explain the purpose of each of the following functions (methods) that can be used with lists: '''append''', '''insert''', '''remove''', '''sort''', '''copy'''.</li>
:# Write the '''functions''' that perform the following operations on a list:<ol type="a"><li>Returns the length of the list</li><li>Returns the smallest value in the list</li><li>Returns the largest value in the list</li></ol>
:# Write a Python script to display all of the elements within a simple list.


[[Category:OPS435-Python]]
[[Category:OPS445]]

Latest revision as of 16:05, 15 January 2025

Functions

You can think of a function as a smaller program within a larger program. The purpose of a function is to help you avoid copy-pasting the same code into multiple places in your program. That may sound like not a big deal, but with any amount of experience you'd find that such copy-pasting inevitably leads to big, unexpected problems. Just imagine for example:

  1. You wrote two pages of code, and it seemed to work,
  2. You copied the apparently working code to 23 places in your large and complicated program,
  3. You had to modify the code slightly in 12 of the 23 places,
  4. 6 months later you found a bug in the original code.
  5. You fixed the original code, and copied it to 21 places, forgetting to modify it as needed in 3 of the 12 places.

In that scenario, especially under the stress programmers usually are: you will almost certainly end up making a mistake similar to #5, and your one bug which should have been easy enough to fix turned into 4 new bugs in code that was already tested and working, and those 4 bugs may not even be discovered for another year.

This is the real value in functions. Building useful functions is not a trivial process, but with experience it will become more and more obvious to you what makes a good function, and when it is worth the effort to create one.

In our simple examples: a function is defined near the top of the file, before the main program. When a program is run, the function's code is read into RAM, ready to be run when the function is called. Until a Function is explicitly called, its code will sit (in RAM) unused.

A function may do one ore more of the following:

  1. Run some useful code
  2. Return a useful value
  3. Receive one or more parameters from the caller

What your function should do depends on what you want/need it to do, but #1 is almost universal, and #2 is almost always done.

Like most of the examples in this course: you have to use your imagination to understand the potential value of these things. The examples are purposefully trivial, to help you understand the basics before you get into actually useful code.

Simple functions with strings

You will now learn how to define and run functions that will return string data when a function is called.

  • Create a new python file for testing code in this section.

Whenever you want to create a function, you must start with the keyword "def". The def keyword is used to start the definition of the function, it does not run the code you write. Functions, just like if statements, must have all code under them indented.

  • Create a function called hello():
    def hello():
        print('Hello World')
        print('Inside a Function')
    
  • Run your program and note that nothing seems to happen. Actually something did happen: the function called hello() has been defined and stored in RAM in order for it to run when called by its function name. But it was never called, so it never printed anything.
  • Now that our function was created, we can use it over and over.
  • To execute the code inside the function, you call it by using the function name followed by one open round bracket and one closed round bracket. Call your hello() function by name three times like this (make sure the calls to hello() are not inside hello(), which is determined by the indentation of the calls:
    hello()
    hello()
    hello()
    

Notice that the function just does the exact same thing no matter how many times your call the function by name. Sometimes that's what you want. At other times you may want your function to work on data which was not there when you wrote your function: for example perform error checking or some other task that returns a value to the main program for further processing.

  • Create a function that returns some data to the caller after it is finished. This function does not print out any text: instead; it creates new variables and at the end returns the value of one of the variables.
    def return_text_value():
        name = 'Terry'
        greeting = 'Good Morning ' + name 
        return greeting
    
  • Call the function like this:
    return_text_value()
    

This probably seems even less useful than the previous useless function, but again: the point is to show you the basic building blocks. Once you understand what you have to work with: you can start thinking of writing useful code.

One major difference between a function returning a value and simply printing a value is that returned values can be stored in variables used in the program (that called the function) for later use. Once the returned value has been stored, it can be printed, manipulated, compared in IF statements, etc.

  • Store the value returned by return_text_value() in a variable named text:
    text = return_text_value()
    
  • Notice that this syntax looks just the call to the input() function which you've used in the last lab.
  • Now that the returned text from the function has been stored in the variable "text", it can be used like any string value. For example you can print it:
    print(text)
    

Simple functions with integers

In this section, you will define a function that will be returning integer values instead of text. There is not a big difference, but you do have to understand that the "data type" concept still applies.

  • Define the return_number_value() function:
    def return_number_value():
        num1 = 10
        num2 = 5
        num3 = num1 + num2
        return num3
    
  • And call it:
    number = return_number_value()
    print(number)
    print(number + 5)
    print(return_number_value() + 10)
    

At this point that code should be pretty self-explanatory.

  • Now, display both strings and numbers:
    number = return_number_value()
    print('my number is ' + number)
    

Your code will execute until the line where you're asking to concatenate a stirng with a number, at which point you get the error you have seen before.

  • Change your code to use the str() function in order to convert the returned number into a string:
    number = return_number_value()
    print('my number is ', number)
    print('my number is ' + str(number))
    print('my number is ' + str(return_number_value()))
    

Importing functions

  • Create a new script ~/ops435/lab3/lab3a.py
  • The script should have a Shebang line
  • Below the Shebang line, add an empty line followed by a comment stating: # return_text_value() function
  • Add an empty line followed by the return_text_value() function definition that you previously entered in your test program.
  • Add another empty line followed by a comment stating: # return_number_value() function
  • Add another empty line following by the return_number_value() function definition that you previously entered in your test program.
  • Add a couple of empty lines, following by a comment stating: # Main Program
  • Add another couple of empty lines, followed by the statements displayed below:
    if __name__ == '__main__':
        print('python code')
        text = return_text_value()
        print(text)
        number = return_number_value()
        print(str(number))
    

Compared to other programming languages that's a backwards way of defining the starting point for your program, but that's how it's done in Python.

Once your program gets complicated enough: you will split it into multiple files. In order to use functions from other files, you use the import statement.

  • Let's see what happens if we forget to import functions from your lab3a.py script prior to calling a function. Create a new python file test2.py and try to call the return_text_value() function:
    text = lab3a.return_text_value()
    

You should notice an error indicating "name 'lab3a' is not defined". This error occurs since you failed to instruct python to import or "load existing defined functions from your lab3a.py program into RAM.

  • Modify your program like this:
    import lab3a
    text = lab3a.return_text_value()
    print(text)
    lab3a.return_number_value()
    

All of the function calls should now work.

  • Download the checking script and check your work. Enter the following commands from the bash shell.
    cd ~/ops435/lab3/
    pwd # confirm that you are in the right directory
    ls CheckLab3.py || wget http://ops345.ca/ops445/CheckLab3.py
    python3 ./CheckLab3.py -f -v lab3a
    
  • Before proceeding, make certain that you identify any and all errors in lab3a.py. When the checking script tells you everything is OK before proceeding to the next step.



Providing Functions With Arguments

Functions can receive arguments - one or more pieces of data. In this section, you will learn how to define functions that accept arguments and call thos functions.

Receiving arguments in a function

When passing arguments to functions, you put data such as strings and numbers within brackets immediately following the function name.

If a function accepts arguments, then those arguments must be declared (using variable names) when the function is declared. Those declared variable names can then used within the function the same way any other declared variables are used.

In this lab: when you call one of your functions with arguments, the number of arguments passed to the function must match the number of arguments that were specified in the function declaration.

  • Create a new Python file for testing.
  • Define a function called square():
    def square(number):
        return number ** 2
    
Idea.png
Power of two
Your probably know that you multiple a number by itself in order to "square" the number (i.e. raise it to the power of two). In python, the ** operator will raise the operand on the left to the power of the operand on the right.
  • Test your square() function:
    square(5)
    square(10)
    square(12)
    square(square(2))
    square('2')
    

Notice that nothing is printed, you need to print the values the functions return to see what they are.

The last function call should produce an error message. This is caused by sending a string instead of a number that is expected by the function. We could use the int() function to convert any value passed in as a string by mistake to an integer number.

  • Declare the function sum_numbers() which will receive two arguments:
    def sum_numbers(number1, number2):
        return int(number1) + int(number2)
    
  • Call that function to see what happens:
    sum_numbers(5, 10)
    sum_numbers(50, 100)
    
  • You can also do what looks like calling a function within another function, but it's actually just calling sum_numbers() first, then calling square() with the return from sum_numbers as an argument:
    square(sum_numbers(5, 5))
    

When you call a function as an argument to another function, the inner-most function will run first, and the return the value from that will be used as the argument for the outer function. In this example sum_numbers(5, 5) will return 10, thus providing that result to be square with that value square(10).

Create a function that accepts arguments and returns a value

  • Create a new program ~/ops435/lab3/lab3b.py. Refer to the Python Program Template, the Sample Run and the Sample Imports sections.

Python Program Template

#!/usr/bin/env python3

def sum_numbers(number1, number2):
    # Make this function add number1 and number2 and return the value

def subtract_numbers(number1, number2):
    # Make this function subtract number1 and number2 and return the value
    # Remember to make sure the function accepts 2 arguments

def multiply_numbers(number1, number2):
    # Make this function multiply number1 and number2 and return the value
    # Remember to make sure the function accepts 2 arguments

if __name__ == '__main__':
    print(sum_numbers(10, 5))
    print(subtract_numbers(10, 5))
    print(multiply_numbers(10, 5))

Sample Run:

./lab3b.py
15
5
50

Other examples:

import lab3b

lab3b.sum_numbers(10, 5)
# Will return 15
lab3b.sum_numbers(25, 25)
# Will return 50
lab3b.subtract_numbers(10, 5)
# Will return 5
lab3b.subtract_numbers(5, 10)
# Will return -5
lab3b.multiply_numbers(10, 5)
# Will return 50
lab3b.multiply_numbers(10, 2)
# Will return 20
  • Download the checking script and check your work:
    cd ~/ops435/lab3/
    pwd # confirm that you are in the right directory
    ls CheckLab3.py || wget http://ops345.ca/ops445/CheckLab3.py
    python3 ./CheckLab3.py -f -v lab3b
    
  • Before proceeding, make certain that you identify any and all errors in lab3b.py. When the checking script tells you everything is OK - proceed to the next step.

A smarter function

You will now create a more complex function that will not only receive arguments, but also include logic to control the flow of the function, and affect the result the function will produce. You will create a function that uses an if/elif/else statement.

  • Use a temporary Python file to define the following function:
    def describe_temperature(temp):
        if temp > 30:
            return 'hot'
        elif temp < 0:
            return 'cold'
        elif temp == 20:
            return 'perfect'
        return 'ok'
    

The final return "ok" will only take place if a previous return has not taken place before it. Once return has been used in a function, the function immediately exits and returns the value.

  • Call describe_temperature() like this to confirm the results:
    print(describe_temperature(50))
    # Should print 'hot'
    print(describe_temperature(20))
    # Should print 'perfect'
    print(describe_temperature(-50))
    # Should print 'cold'
    print(describe_temperature(25))
    # Should print 'ok'
    print(describe_temperature(10))
    # Should print 'ok'
    
  • Create the ~/ops435/lab3/lab3c.py program. The purpose of the program is to have a single function that can perform addition, subtraction, or multiplication on a pair of numbers. But the function will allow us to choose exatly what operation we are performing on it when we call it. If the operate function does NOT understand the operator given, it should return an error message (e.g. calling the function to 'divide' two numbers).
  • Use this template to get started:
    #!/usr/bin/env python3
    
    def operate(number1, number2, operator):
        # Place logic in this function
    
    if __name__ == '__main__':
        print(operate(10, 5, 'add'))
        print(operate(10, 5, 'subtract'))
        print(operate(10, 5, 'multiply'))
        print(operate(10, 5, 'divide'))
    
  • Complete the function considering the following requirements:
  1. The operate() function should use conditional statements.
  2. The operate() function should accept three arguments.
  3. The operate() function should return the result.
  4. The operate() function should return an error message (a string) if the operation is unknown.
  5. The program should contain show the exact output as the sample.
  6. As an extra exercise, try to write your function with only one return statement.

Sample Run 1:

./lab3c.py
15
5
50
Error: function operator can be "add", "subtract", or "multiply"

Sample Run 2 (using import from another Python file):

import lab3c
lab3c.operate(10, 20, 'add')
# Will return 30
lab3c.operate(2, 3, 'add')
# Will return 5
lab3c.operate(100, 5, 'subtract')
# Will return 95
lab3c.operate(10, 20, 'subtract')
# Will return -10
lab3c.operate(5, 5, 'multiply')
# Will return 25
lab3c.operate(10, 100, 'multiply')
# Will return 1000
lab3c.operate(100, 5, 'divide')
# Will return Error: function operator can be "add", "subtract", or "multiply"
lab3c.operate(100, 5, 'power')
# Will return Error: function operator can be "add", "subtract", or "multiply"
  • Download the checking script and check your work. Enter the following commands from the bash shell.
    cd ~/ops435/lab3/
    pwd #confirm that you are in the right directory
    ls CheckLab3.py || wget http://ops345.ca/ops445/CheckLab3.py
    python3 ./CheckLab3.py -f -v lab3c
    
  • Before proceeding, make certain that you identify any and all errors in lab3c.py. When the checking script tells you everything is OK - proceed to the next step.

Running System Commands

You to run operating system commands from your Python program. There are several different ways to issue operating system commands, you will learn two of them.

In some ways calling a program is very similar to calling a function, but the underlying mechanism for doing that is completely different, so don't expect it to work exactly the same way.

  • Create a new python file for testing.
  • Import the os module in your python file.
  • You can issue operating system commands by using the system() function. Try it:
    os.system('ls')
    os.system('whoami')
    os.system('ifconfig')
    

Notice that the output from the programs is printed in your program. Consider that may not always be what you want.

  • Try this also:
    os.system('ipconfig')
    

You should notice an error message: 'ipconfig: command not found'. That error occurs since that command was a Windows command, and our current platform is Linux. If you're really paying attention: you will notice that the error is a shell error, not a python error.

It is not always a good idea to run system commands in Python, this makes your Python code less portable and makes it require a specific operating system or a system that has those commands available. You should think about that when you decide whether you should or should not use a system command to accomplish some task or stick to pure Python code only.

Another way to run commands is using the subprocess module.

  • Import the subprocess module in your python file.
  • There are many features available as part of the subprocess module, we are interested in "Popen".
  • This subprocess.Popen() function can be used to run system commands as a child process to the Python script. The code below output will create a new child process, in Python we can control this through the new Python object we just created, "p". "p" will have a collection of methods(functions that are apart of a object) available.
  • To demonstrate, try the following:
    p = subprocess.Popen(['date'], stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
    

This function call and the following step is full of details we haven't yet talked about which is why it may look a little scary. By the time we're finished with the course - you will be able to look at code like this and not be intimidated. If you're curious and want to look ahead - you can find the definition for the Popen function in the Python reference manual.

  • Communicate with the process and retrieve its output (stdout).
    output = p.communicate()
    print(output)
    print(output[0])
    # The above stdout is stored in bytes
    # Convert stdout to a string and strip off the newline characters
    stdout = output[0].decode('utf-8').strip()
    print(stdout)
    

Sometimes you will be able to use purely python code to get your job done, but often you will need to call existing system commands. It's important to learn how to call them and how to interact with those external processes.

  • Create the "~/ops435/lab3/lab3d.py" program. Create a Python function that can return the linux system's root filesystem's free space.
  • The program should import the correct module
  • The program should use the linux command: df -h | grep '/$' | awk '{print $4}'
  • The program should contain the function called: free_space()
  • The function free_space() should return a string which is in utf-8 and has no newline in the end.
  • Your output may be different, the free/available disk space on different computers is rarely the same.


Sample Run 1:

./lab3d.py
9.6G

Sample Run 2 (using import from another Python file):

import lab3d
lab3d.free_space()
# Will return 9.6G
  • Download the checking script and check your work:
    cd ~/ops435/lab3/
    pwd #confirm that you are in the right directory
    ls CheckLab3.py || wget http://ops345.ca/ops445/CheckLab3.py
    python3 ./CheckLab3.py -f -v lab3d
    
  • Before proceeding, make certain that you identify any and all errors in lab3d.py. When the checking script tells you everything is OK - proceed to the next step.

Lists

A List is a non-trivial data-type in Python. You define a list using a series of comma separated values found between square brackets. Values in a list can be anything: strings, integers, objects, even other lists.

It is important to realise that although lists may appear very similar to arrays in other languages, they are different in a number of aspects including the fact that they don't have a fixed size.

Navigating items in lists

  • Create a new Python file for testing things in this section.
  • Create three lists with different values: list1 contains only integers, list2 contains only strings, list3 contains a combination of both integers and strings
    list1 = [1, 2, 3, 4, 5, 6, 7, 8, 9]
    list2 = ['uli101', 'ops235', 'ops335', 'ops435', 'ops535', 'ops635']
    list3 = ['uli101', 1, 'ops235', 2, 'ops335', 3, 'ops435', 4, 'ops535', 5, 'ops635', 6]
    

The simplest way to access individual elements in a list is using the list index.

The index is a number starting from 0 to (number_of_items - 1). The index of the first element is 0.

  • Inspect specified elements in your lists:
    print(list1[0])  # First element in list1
    print(list2[1])  # Second element in list2
    print(list3[-1]) # Last element in list3
    
  • You can also retrieve ranges of items from a list (these are called slices):
    print(list1[0:5]) # Starting with index 0 and stopping before index 5
    print(list2[2:4]) # Starting with index 2 and stopping before index 4
    print(list3[3:])  # Starting with index 3 and going to the end
    
  • Create a Python program called: ~/ops435/lab3/lab3e.py

The program will have a number of functions which output various parts of a list. Each function will return either a single item from the list OR will create a new list and return the entire new list.

  • Start with this template:
    #!/usr/bin/env python3
    
    # Create the list called "my_list" here, not within any function defined below.
    # That makes it a global variable. We'll talk about that in another lab.
    
    
    def give_list():
        # Does not accept any arguments
        # Returns all of the global variable my_list unchanged
    
    def give_first_item():
        # Does not accept any arguments
        # Returns a single string that is the first item in the global my_list
    
    def give_first_and_last_item():
        # Does not accept any arguments
        # Returns a list that includes the first and last items in the global my_list
    
    def give_second_and_third_item():
        # Does not accept any arguments
        # Returns a list that includes the second and third items in the global my_list
    
    if __name__ == '__main__':   # This section also referred to as a "main code"
        print(give_list())
        print(give_first_item())
        print(give_first_and_last_item())
        print(give_second_and_third_item())
    
  • Here's what you need to do:
  1. The script should declare a list called my_list created BEFORE any function definition
  2. The list called my_list should have the values: 100, 200, 300, and "six hundred"
  3. The script should implement the empty functions - i.e. you have to fill in the bodies for these functions

Sample Run 1:

./ lab3e.py
[100, 200, 300, 'six hundred']
100
[100, 'six hundred']
[200, 300]

Sample Run 2 (with import from another script):

import lab3e
lab3e.give_list()
# Will print [100, 200, 300, 'six hundred']
lab3e.give_first_item()
# Will print 100
lab3e.give_first_and_last_item()
# Will print [100, 'six hundred']
lab3e.give_second_and_third_item()
# Will print [200, 300]
  • Download the checking script and check your work:
    cd ~/ops435/lab3/
    pwd # confirm that you are in the right directory
    ls CheckLab3.py || wget http://ops345.ca/ops445/CheckLab3.py
    python3 ./CheckLab3.py -f -v lab3e
    
  • Before proceeding, make certain that you identify any and all errors in lab3e.py. When the checking script tells you everything is OK - proceed to the next step.

Manipulating items in lists

There is a number of ways to obtain information about lists as well as change the data that is contained within a list. In this section, you will learn how to manipulate lists.

  • Let's perform a simple change to a list element. Try the following code in a temporary python file:
    courses = ['uli101', 'ops235', 'ops335', 'ops435', 'ops535', 'ops635']
    print(courses[0])
    courses[0] = 'eac150'
    print(courses[0])
    print(courses)
    
  • Below are some examples of using built-in functions to manipulate lists. Take your time to see how each function can be a useful tool for making changes to existing lists:
    courses.append('ops235')    # Add a new item to the end of the list
    print(courses)
    
    courses.insert(0, 'hwd101') # Add a new item to the specified index location
    print(courses)
    
    courses.remove('ops335')    # Remove first occurrence of value
    print(courses)
    
    sorted_courses = courses.copy() # Create a copy of the courses list
    sorted_courses.sort()           # Sort the new list
    print(courses)
    print(sorted_courses)
    
  • In addition to using functions to manipulate lists, there are functions that are useful to provide information regarding the list such as number of elements in a list, the smallest value and largest value in a list:
    list_of_numbers = [ 1, 5, 2, 6, 8, 5, 10, 2 ]
    length_of_list = len(list_of_numbers)    # Returns the length of the list
    smallest_in_list = min(list_of_numbers)  # Returns the smallest value in the list
    largest_in_list = max(list_of_numbers)   # Returns the largest value in the list
    
    # Notice how the long line below is wrapped to fit on one editor screen, so you don't need to scroll to read it:
    print("List length is " + str(length_of_list) + 
          ", smallest element in the list is " + str(smallest_in_list) +
          ", largest element in the list is " + str(largest_in_list))
    

Iterating over a list using the for loop

This last section demonstrates a quick and easy way to loop through every value in the list. For loops have a set number of times they loop. The for loop will execute all indented code for each item (element) in the list.

Other programming languages that have a loop such as this: it is usually called a "foreach" loop.

The following for loop's body will execute as many times as there are elements in the list_of_numbers. For each element: it will store its value in a variable named item; and run code indented below.

  • Create a temporary Python file with these contents and run it:
    list_of_numbers = [1, 5, 2, 6, 8, 5, 10, 2]
    for item in list_of_numbers:
        print(item)
    
  • As you can see: instead of writing eight function calls for each element of the list, we can call the print() function in a loop. And we won't have to rewrite code if the length of the list changes.
  • Run the following code:
    list_of_numbers = [1, 5, 2, 6, 8, 5, 10, 2]
    
    def square(num):
        return num * num
    
    for value in list_of_numbers:
        print(square(value))
    

The code above only prints the squares and does not save them for future use. The next example uses a function that loops through list, squares the values, and also saves the squares in a new list.

  • Run the following code:
    list_of_numbers = [1, 5, 2, 6, 8, 5, 10, 2]
    
    # Squares each item in a list of numbers, returns new list with squared numbers
    def square_list(number_list):
        new_list = []
        for number in number_list:
            new_list.append(number * number)
        return new_list
    
    new_list_of_numbers = square_list(list_of_numbers)
    print(list_of_numbers)
    print(new_list_of_numbers)
    

The above is just one example of a quick use of for loops mixed with lists. But be careful when passing lists into functions. When you give a function a list as an argument, it is the actual list reference and NOT a copy. This means a function can change the list without making a new list. While you do have to be careful, this can also be useful. A function can modify any given list without having to return it.

  • To demonstrate, run the following code:
    list_of_numbers = [ 1, 5, 2, 6, 8, 5, 10, 2 ]
    def delete_numbers(numbers):
        numbers.remove(5)
        numbers.remove(6)
        numbers.remove(8)
        numbers.remove(5)
    delete_numbers(list_of_numbers)
    print(list_of_numbers)
    

Practice with Functions, Lists, and Loops

  • Create the ~/ops435/lab3/lab3f.py script. The purpose of this script is to use functions to modify items inside a list.
  • Start with this:
    #!/usr/bin/env python3
    
    # Place my_list below this comment (before the function definitions)
    
    
    
    def add_item_to_list(ordered_list):
        # Appends new item to end of list with the value (last item + 1)
    
    def remove_items_from_list(ordered_list, items_to_remove):
        # Removes all values, found in items_to_remove list, from my_list
    
    # Main code
    if __name__ == '__main__':
        print(my_list)
        add_item_to_list(my_list)
        add_item_to_list(my_list)
        add_item_to_list(my_list)
        print(my_list)
        remove_items_from_list(my_list, [1,5,6])
        print(my_list)
    
  • Complete the program following these requirements:
  1. The missing list should have the values: 1, 2, 3, 4, 5
  2. The program should have a function called add_item_to_list(ordered_list). This function takes a single argument which is expected to be of type list. The function will retrieve the value of the last item in the list, and it will append a new value to that list so that the new value is one unit bigger than the previous last element.
  3. The add_item_to_list() function will modify the list it receives via the parameter, and will not return anything.
  4. The program should have a function called remove_items_from_list(ordered_list, items_to_remove). This function takes two arguments: a list, and a second list of numbers to remove from the first list. For each item in the second list the function will check if that item exists in the first list, and if it exists: remove it.
  5. The remove_items_from_list() function will modify the ordered_list without returning any value.

Sample Run 1:

run lab3f.py
[1, 2, 3, 4, 5]
[1, 2, 3, 4, 5, 6, 7, 8]
[2, 3, 4, 7, 8]

Sample Run 2 (with import):

from lab3f import *                                                                                                                                                            print(my_list)
# Will print [1, 2, 3, 4, 5]
add_item_to_list(my_list)
add_item_to_list(my_list)
add_item_to_list(my_list)
print(my_list)
# Will print [1, 2, 3, 4, 5, 6, 7, 8]
remove_items_from_list(my_list, [1,5,6])
print(my_list)
# Will print [2, 3, 4, 7, 8]
  • Download the checking script and check your work. Enter the following commands from the bash shell.
    cd ~/ops435/lab3/
    pwd # confirm that you are in the right directory
    ls CheckLab3.py || wget http://ops345.ca/ops445/CheckLab3.py
    python3 ./CheckLab3.py -f -v lab3f
    
  • Before proceeding, make certain that you identify any and all errors in lab3f.py. When the checking script tells you everything is OK - proceed to the next step.

Submit evidence of your work

Run the following command in a terminal:

cd ~/ops435/lab3
python3 ./CheckLab3.py -f
  • The output of the lab check command must say OK.
  • To show that you completed the lab, submit a screenshot of the terminal with that output.