Difference between revisions of "Rchan sandbox"

From CDOT Wiki
Jump to: navigation, search
(Part 1 - Simple Object Class with external functions)
Line 199: Line 199:
 
:8. Before proceeding, make certain that you identify all errors in lab7b.py. When the checking script tells you everything is OK - proceed to the next step.
 
:8. Before proceeding, make certain that you identify all errors in lab7b.py. When the checking script tells you everything is OK - proceed to the next step.
 
<br><br>
 
<br><br>
 +
 +
==Part 3 - Another approach to perform  operation on time objects ==
 +
In the previous parts, we recognise that fact that a Time object is essentially a three-digit number in base 60. The 'second' attribute is the "ones colume", the 'minute' attribute is the "sixties column", and the hour attribute is the '60 x 60' column. This is why we have to carry over second to minute when the value of 'second' exceeds 60.
 +
 +
In this part, we are going to use a different approach to manage calculation on Time object. We know that there are 86400 (24 x 60 x 60) seconds in a day. It is relatively easy to convert a Time object in the form of hour:minute:second to be represent by a single integer value in seconds. It is equally straight forward to convert a integer number of seconds between 0 and 86399 into hour:minute:second format. Here are two functions: sec_to_time(seconds) and time_to_sec(time) that will do just that:<source lang="python">
 +
...
 +
...
 +
def time_to_sec(time):
 +
    '''convert a time object to a single integer representing the number of seconds from mid-night'''
 +
    minutes = time.hour * 60 + time.minute
 +
    seconds = minutes * 60 + time.second
 +
    return seconds
 +
 +
def sec_to_time(seconds): 
 +
    '''convert a given number of seconds to a time object in hour,minute,second format'''
 +
    time = Time()
 +
    minutes, time.second = divmod(seconds, 60)
 +
    time.hour, time.minute = divmod(minutes,60)
 +
    return time
 +
...
 +
...
 +
</source>

Revision as of 17:43, 2 November 2019

OPS435 Python Lab 7

OBJECTIVES

  1. Create functions to process programmer-defined type objects.
  2. Binding functions into methods for programmer-defined type objects.

Overview

Object-oriented programming is conceptually one level higher than simply structured programming style as you've experienced in Bash or C. In this lab, we're going to look at a few object-oriented programming examples using the Python language.

Reference:

  • Time object from Think Python Chapter 16 and 17
  • Date object from OPS435 Assignment 1

Investigation I: Objects and Functions

Part 1 - Simple Object Class with external functions

In this part, we consider a time object which has three data attributes, namely: hour, minute, and second. The following Python script lab7a.py provides the blue print for building such a time object and also defines three external functions: format_time(), sum_times(), and valid_time(), which can manipulate the time object.

#!/usr/bin/env python3

class Time:
   """Simple object type for time of the day.
      data attributes: hour, minute, second
   """
   def __init__(self,hour=12,minute=0,second=0):
       """constructor for time object""" 
       self.hour = hour
       self.minute = minute
       self.second = second

def format_time(t):
    """Return time object (t) as a formatted string"""
    return '%.2d:%.2d:%.2d' % (t.hour, t.minute, t.second)

def sum_times(t1, t2):
    """Add two time objests and return the sum."""
    sum = Time(0,0,0)
    sum.hour = t1.hour + t2.hour
    sum.minute = t1.minute + t2.minute
    sum.second = t1.second + t2.second
    
    return sum

def valid_time(t):
    """check for the validity of the time object attributes:
       24 > hour > 0
       60 > minute > 0
       60 > second > 0 """
    if t.hour < 0 or t.minute < 0 or t.second < 0:
       return False
    if t.minute >= 60 or t.second >= 60 or t.hour >= 24:
       return False
    return True
Perform the following steps:
1. Download or create the above Pythone script lab7a.py in your ~/ops435/lab7 directory.
2. Create a new Python script named lab7a1.py in the lab7 directory:
cd ~/ops435/lab7
vi ~/ops435/lab7/lab7a1.py
3. Place the following content inside the new python file lab7a1.py and save it:
#!/usr/bin/env python3
# Student ID: [seneca_id]
from lab7a import *
t1 = Time(8,0,0)
t2 = Time(8,55,0)
t3 = Time(9,50,0)

td = Time(0,50,0)

tsum1 = sum_times(t1,td)
tsum2 = sum_times(t2,td)
tsum3 = sum_times(t3,td)   

ft = format_time
print(ft(t1),'+',ft(td),'-->',ft(tsum1))
print(ft(t2),'+',ft(td),'-->',ft(tsum2))
print(ft(t3),'+',ft(td),'-->',ft(tsum3))
4. The above python script lab7a1.py should produce the following output when executed:
[rchan@centos7 lab7]$ python3 lab7a1.py
08:00:00 + 00:50:00 --> 08:50:00
08:55:00 + 00:50:00 --> 08:105:00
09:50:00 + 00:50:00 --> 09:100:00
5 If you pay a little bit attention on the outputs, you should notice that the sum_times() function did not carry 60 minutes over to hour. It also will not carry 60 seconds over to minute.
6 To fix that problem, perform the following:
(a) Edit the file lab7a.py and modify the function sum_times(). Add code to check the values of the time object's three attributes. If the value of the minute attribute is more than 60, carry it over to the hour until it is less than 60. Do the same for the value of the second attribute.
(b) The illustration below indicates where you should perform the carry over operation in the sum_times() function in lab7a.py:
...
...
def sum_times(t1, t2):
    """Add two time objests and return the sum."""
    sum = Time(0,0,0)
    sum.hour = t1.hour + t2.hour
    sum.minute = t1.minute + t2.minute
    sum.second = t1.second + t2.second
    
    #[ insert python code here to check for minute and second 
    #[ attribute here, and carry over when necessary
    #[
    return sum
...
...
(c) Save the file.
(d) Test run your script lab7a1.py again and make sure that it produces the output to match the following exactly:
[rchan@centos7 lab7]$ python3 lab7a1.py
08:00:00 + 00:50:00 --> 08:50:00
08:55:00 + 00:50:00 --> 09:45:00
09:50:00 + 00:50:00 --> 10:40:00
7. Download the checking script and check your work. Enter the following commands from the bash shell.
cd ~/ops435/lab7/
pwd #confirm that you are in the right directory
ls CheckLab7.py || wget https://ict.senecacollege.ca/~raymond.chan/ops435/labs/LabCheckScripts/CheckLab7.py
python3 ./CheckLab7.py -f -v lab7a
8. Before proceeding, make certain that you identify all errors in lab7a.py. When the checking script tells you everything is OK - proceed to the next step.



Part 2 - Pure Function and Modifiers

In Part 1, the sum_times() function will not make any change to any of the two time objects. It is called a pure function. In this part, we are going to create a function which changes the value (the three attributes) of a time object based on the integer value passes to the function. We call such type of function a modifier. The function we are going to add is called change_time(time, seconds): where time is the time object the function is going to modify, and seconds is the number of seconds the function will add to the time object.

1. Make a copy of lab7a.py and name it as lab7b.py in the ~/ops435/lab7 directory
2. Add the following new function called change_time(time, seconds) after the sum_times() function:
def change_time(time, seconds):
    time.second += seconds
    if valid_time(time) != True:
        while time.second >= 60:
             time.second -= 60
             time.minute +=1
        while time.minute >= 60:
             time.minute -= 60
             time.hour += 1
    return None
3. Save the file.
4. Bring up an interact Python3 shell to test the new function.
Testing change_time(time, seconds) with import
[rchan@centos7 wiki_labs]$ python3
Python 3.4.9 (default, Aug 14 2018, 21:28:57) 
[GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from lab7b import *
>>> time1 = Time(9,50,0)
>>> format_time(time1)
'09:50:00'
>>> seconds = 1800
>>> seconds
1800
>>> change_time(time1, seconds)
>>> format_time(time1)
'10:20:00'
5 If you encounter any syntax error or exception, please fix the error before moving on to the next step.
6 Now try set seconds to a negative value, i.e. -1800, and then call the change_time() function.
Will it change the time1 object back to '09:50:00'? Let's try it out:
>>> format_time(time1)
'10:20:00'
>>> seconds = -1800
>>> change_time(time1, seconds)
>>> format_time(time1)
'10:20:-1800'
7. It is not correct! So we have to modify and update the change_time() function so that the change_time() function can handle positive and negative value correctly. After the function change_time() has been updated, test it again in a Python interactive shell with import
[rchan@centos7 wiki_labs]$ python3
Python 3.4.9 (default, Aug 14 2018, 21:28:57) 
[GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> format_time(time1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'format_time' is not defined
>>> from lab7b import *
>>> time1 = Time(9,50,0)
>>> format_time(time1)
'09:50:00'
>>> seconds = 1800
>>> change_time(time1, seconds)
>>> format_time(time1)
'10:20:00'
>>> seconds = -1800
>>> change_time(time1, seconds)
>>> format_time(time1)
'09:50:00'
7. Download the checking script and check your work. Enter the following commands from the bash shell.
cd ~/ops435/lab7/
pwd #confirm that you are in the right directory
ls CheckLab7.py || wget https://ict.senecacollege.ca/~raymond.chan/ops435/labs/LabCheckScripts/CheckLab7.py
python3 ./CheckLab7.py -f -v lab7b
8. Before proceeding, make certain that you identify all errors in lab7b.py. When the checking script tells you everything is OK - proceed to the next step.



Part 3 - Another approach to perform operation on time objects

In the previous parts, we recognise that fact that a Time object is essentially a three-digit number in base 60. The 'second' attribute is the "ones colume", the 'minute' attribute is the "sixties column", and the hour attribute is the '60 x 60' column. This is why we have to carry over second to minute when the value of 'second' exceeds 60.

In this part, we are going to use a different approach to manage calculation on Time object. We know that there are 86400 (24 x 60 x 60) seconds in a day. It is relatively easy to convert a Time object in the form of hour:minute:second to be represent by a single integer value in seconds. It is equally straight forward to convert a integer number of seconds between 0 and 86399 into hour:minute:second format. Here are two functions: sec_to_time(seconds) and time_to_sec(time) that will do just that:
...
...
def time_to_sec(time):
    '''convert a time object to a single integer representing the number of seconds from mid-night'''
    minutes = time.hour * 60 + time.minute
    seconds = minutes * 60 + time.second
    return seconds

def sec_to_time(seconds):   
    '''convert a given number of seconds to a time object in hour,minute,second format'''
    time = Time()
    minutes, time.second = divmod(seconds, 60)
    time.hour, time.minute = divmod(minutes,60)
    return time
...
...