WEEK07: File I/O, top-down design
---------------------------------------------------------------
 M: File Input/Output

REVIEW:

 - Quiz 3 review
 - Lab 6 due this Thursday
 - Lab 7 will be up on Wednesday

What's the difference between the following two functions?
They are both looking for the character ch in the string S.
One of them doesn't work as advertised...

# --------------------------------------------------- #

def lookFor(S, ch):
  """return True if ch in S"""

  for letter in S:
    if letter == ch:
      # found it...so immediately return to caller
      return True 

  # only gets here if for loop is done and char is not found
  return False

# --------------------------------------------------- #

# Here's how most new programmers try to write that:

def lookFor(S, ch):
  """this function does NOT work"""

  for letter in S:
    if letter == ch:
      return True 
    else:
      return False

# --------------------------------------------------- #
see the difference??! what would lookFor("we love CS", "e") return???!


FILE I/O:

 - motivations:
    * video game data files (read in terrain data; high scores)
    * grader.py: store student grade data in a file (don't have to 
       type it in each time the program runs)
    * iTunes: how does iTunes keep track of # of plays for each song??

 - files can be just text files, like you edit with vim

OUTPUT:
 - here's how to open a file for writing (note: myfile is a variable
   name that I choose, and "newfile" is the name of the file to write to):

$ python
>>> myfile = open("newfile", 'w')
>>> type(myfile)
<type 'file'>
(a new python type!!)
>>> myfile.write("write this to the file \n")
>>> myfile.write("and this.... \n")
>>> myfile.close()

 - and here are the results of this:

$ ls
newfile
$ cat newfile 
write this to the file 
and this.... 

 - what happens if we leave out the \n's on each line??

INPUT:
 - to open a file for reading, use 'r' mode:

>>> infile = open("words.txt", 'r')

 - file "words.txt" must exist, otherwise we get an error

 - note: infile is a variable of type file:

>>> type(infile)
<type 'file'>

 - and it can be used as a sequence (in a for loop!):

>>> for line in infile:
...    print line 
... 
happy

birthday

computer

smile

FILE I/O NOTES:

 - reading from and writing to files is usually SLOW
 - for this reason, we usually read in data at the beginning of a
   program and store it in a list or other data structure (ie, if we
   need the data throughout the program, it's much faster to
   refer to the list rather than the file over and over)
 - also, reading from the file is similar to watching a movie on
   VHS tapes -- at the end of the movie, you have to rewind the tape
   to get back to the beginning. Once we do that "for line in infile"
   loop above, we are at the end of the file. You can "rewind" the
   file by closing and reopening it (or use the seek() method in python)
 
EXAMPLE:

 - suppose we have a file of usernames and grades, like this:

$ cat grades.txt 
lisa     :95
jeff     :35
jason    :88
adam     :97
frances  :96
rich     :77

 - here's a program to figure out the average of those grades:

# store grades in python list, in case we need them later
grades = []

# read all grades into a list
gfile = open("grades.txt", "r")
for line in gfile:
  name, grade = line.split(":")   # split in two, based on colon
  grades.append(float(grade))
gfile.close()

# find ave of grades in list
total = 0.0
for g in grades:
  total += g
ave = total/len(grades)
print "ave grade = ", ave


YOUR TURN:

 - how would you read in multiple quiz grades for each student,
   finding the ave quiz grade for each student?

$ cat quizgrades.txt 
lisa    :98,100,95,93,99
jeff    :58,50,55,53,59
rich    :88,78,89,75,79
frances :67,78,89,90,99

$ python quizgrades.py 

      lisa:  97.0
      jeff:  55.0
      rich:  81.8
   frances:  84.6