[Tutor] Reading from files problem

Alan Gauld alan.gauld at btinternet.com
Mon Apr 20 08:59:15 CEST 2009

"Chris Castillo" <ctcast at gmail.com> wrote 

>I am trying to open a text file and read multiple lines containing the
> following:
> 745777686,Alam,Gaus,CIS,15,30,25,15,5,31,15,48,70,97
> 888209279,Anderson,Judy,Math Ed,14,30,30,13,11,30,16,18,58,72

You could use the CSV module for this, although a basic 
for loop is fine too if the data is this simple.

> I want to ask the user for the student number, check to see if that
> number is even valid and display something like:

You might want to store the data in a dictionary keyed by ID number?

> #Open and read text file
> gradesfile = open("grades.dat", "r"
> for lines in gradesfile:
>    lines = lines.split(",")
>    identifier = lines[0]
>    lastname = lines[1]
>    firstname = lines[2]
>    major = lines[3]

OK so far

>    hw1 = lines[4]
>    hw2 = lines[5]
>    hw3 = lines[6]
>    hw4 = lines[7]
>    hw5 = lines[8]
>    hw6 = lines[9]
>    hw7 = lines[10]

You could store these in a list using list slicing, and convert 
to numbers using a list comprehension

hw = [float(n) for n in lines[4:11]]

>    test1 = lines[11]
>    test2 = lines[12]
>    test3 = lines[13]

And here:

test = [float(n) for n in lines[11:14]]

>    totalpoints = 550
>    hwgrades = float(hw1) + float(hw2) + float(hw3) + float(hw4) +
> float(hw5) + float(hw6) + float(hw7)

You could then use sum() to get the totals

hwgrades = sum(hw)

>    testgrades = float(test1) + float(test2) + float(test3)

testgrades = sum(test)

>    studentpoints = float(hwgrades) + float(testgrades)

you don;t need the flooat conversions because you already 
did that above.

>    avgrades = round(float(studentpoints / totalpoints) * 100.0, 2)

same here.

>    print identifier
> gradesfile.close()

> That's what I have so far but I have a feeling I shouldn't use a for
> loop. I would really like any help trying to figure out this program.
> Thanks in advance.

Thats all fine for reading one stiudent, but you overwrite the 
data each time through the loop! This also looks like an obvious 
use for a class so I'd create a Student class to hold all the data
(You could create methods to do the totals/averages too, plus 
add a __str__  method to print the student data in the format 
required- I'll leave that as an excercise for the reader!))

So I'd change the structure to be like this(pseudo code)

students = dict()  # empty dict
for line in gradesfile:
    line = line.split(',')
    s = Student()
    s.id = line[0]
    s.lastname = line[1]
    s.hwtotal = sum(hw)
    students[s.id] = s

Now you can access/print any student record with

id = raw_input('type an id number')
s = students[id]
print s

Finally you could put the for loop inside the Student 
class __init__ method so it boils down to:

for line in gradesfile:
     s = Student(line)
     students[s.id] = s

In fact you could cram it all into one line with another 
list comprehension, but that seems like a step too far to me...


Alan Gauld
Author of the Learn to Program web site

More information about the Tutor mailing list