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

 - Quiz 3 on FRIDAY
 - Lab 6 due Saturday


- craps.py: let's add one more function to the game: what do
  we need to do the "play for point" section???

     * keep rolling until we get:
          7 and lose
          original roll and win
     * if we make this a function, we'll need the original roll
     * if we make this a function, what should it return? Probably
       True/False to be like playOneGame()

def playOneGame():
  """ Plays a single of craps
      Returns True if player wins, False otherwise
  """
  print "Playing one game"
  roll = rollTwoDice()
  if roll == 2 or roll == 3 or roll == 12:
    return False
  elif roll == 7 or roll == 11:
    return True
  else:
    #play for point
    return playForPoint(roll)
    

def playForPoint(originalroll):
  """
  roll dice until we get 7 or original roll.
  return True for win (orig roll), False for lose (7)
  """

  while True:
    roll = rollTwoDice()
    if roll == 7:
      return False
    elif roll == originalroll:
      return True
    else:
      print "rolling again..."


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:
 - I have a file called "words.txt" with a few words in it:

$ cat words.txt 
happy
computer
lemon
zebra

 - 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

computer

lemon

zebra

 - we can use the for loop like above, or we could use the
   file methods: readline() to read one line
                 readlines() to read them all at once

>>> infile.close()      # need to close and reopen to get back to start of file
>>> 
>>> infile = open("words.txt", "r")
>>> word = infile.readline()
>>> print word
happy

>>> word = infile.readline()
>>> print word
computer

>>> infile.close()
>>> infile = open("words.txt", "r")
>>> words = infile.readlines()
>>> print words
['happy\n', 'computer\n', 'lemon\n', 'zebra\n']

 - so readlines() reads in EVERYTHING and puts each line into a python list
   (NOTE: the newline characters are still part of each line!)

 - sometimes you want to read in EVERYTHING, all at once
 - sometimes it's better to read data in line-by-line and process
   each line as you go (use the for loop: for line in infile)


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)
 - 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