简体   繁体   中英

Python creating an Object while reading file

I wrote a simple Python script to determine if all students grades are reported. The script first loops through and adds students to arrays regarding grade status. Then I loop through the file again, to determine if each students grades are in. I end up with three arrays that include students with "all grades reported", "some grades reported", "no grades reported". However, I want tackle this problem with more of a object oriented approach. I have attempted to create a class that works. I am stuck at how to loop through and create one Object for each student, then use addcourse to push each course into the Object. Any help I can get to become a better programmer would be great!

Data:

**id,fname,lname,course,grade,mode**
10001,Freddy,Freshman,Art-101,A,online
10001,Freddy,Freshman,Art-101,A,online
10002,Suize,Sophmore,Mat-102,C,inperson
10002,Suize,Sophmore,Bio-101, ,inperson
10002,Suize,Sophmore,Soc-201,D,online
10003,Jilly,Junior,mth-102, ,inperson
10003,Jilly,Junior,Bus-101, ,inperson
10003,Jilly,Junior,Che-204, ,inperson

Working Code:

fh = open('students.txt').readlines()
header = fh.pop(0)
gradereported = []
nogradereported = []
    for line in fh:
        students = line.split(',')
        ids = students[0]
        grade = students[4]
        if grade != "":
            gradereported.append(ids)
        else:   
            nogradereported.append(ids)
allgradesin =[]
nogradesin = []
somegradesin = []
for i in fh:
    students = line.split(',')
    ids = students[0]
    if ids in gradereported and ids not in nogradereported:
            if ids not in allgradesin:
                    allgradesin.append(ids)
    elif ids not in gradereported and ids in nogradereported:
            if ids not in nogradesin:
                    nogradesin.append(ids)
    elif ids in gradereportedand and ids in nogradereported:
            if ids not in somegradesin:
                    somegradesin.append(ids)

Attempt at class:

class Student(object):
    def __init__(self, lname, fname, term, courses = []):
        self.studid = studid
        self.lname = lname
        self.fname = fname
        self.term = term
        self.courses = []

    def addcourse(self, course, grade, mode):
        self.course = course
        self.grade = grade
        self.mode = mode
        self.courses.append((self.course, self.grade, self.mode))

You could do this, as @blade suggests, by creating a dictionary indexed by student id and then for each row of your input file either get the existing student from the dictionary if it exists or create a new one. In code, this would look like:

class Student(object):
    def __init__(self, student_id, lname, fname):
        self.studid = student_id
        self.lname = lname
        self.fname = fname
        self.courses = []

    def addcourse(self, course, grade, mode):
        self.courses.append((course, grade, mode))

students = {}

fh = open('students.txt').readlines()
header = fh.pop(0)

for line in fh:
    row = line.split(',')
    if len(row) < 6:
        continue

    student_id, fname, lname, course, grade, mode = [i.strip() for i in row]

    student = students.get(student_id, Student(student_id, lname, fname))
    student.addcourse(course, grade, mode)
    students[student_id] = student

A couple of things to note. First, I modified the constructor of your Student class, dropping the term argument since it wasn't clear where the term was specified in your input file. Furthermore, since you don't use the courses argument I dropped that as well. (Note that you probably don't want to use [] as a default argument. Read about mutable default arguments here .) You also don't need to create instance variables for the course, grade, and mode in your addcourse function, you can just append them directly to the array.

I also added a call to strip for each of the items pulled from the input file to clean up the newlines at the end of each row.

How about this:

  1. Add a dict that id is the key, and the Student object is the value
  2. Loop the file and if the key is in the dict, get the Student object from the dict. Otherwise create a new Student object. Then add the course to the Student object.

In addition to the answer of @JCVanHanne you could define another function in your class to collect the info, whether a student has none, some or all of his/her grades.

One possible way (assuming a missing grade is represented by an empty string while also grades like A+ or other none-empty values are possible) could be:

def gradeStatus(self):
    miss = [course[1] for course in self.courses].count("") # count empty grades
    if len(self.courses) == miss:
        print('No grades at all')
    elif miss in range(1, len(self.courses)):
        print('Some, but not all grades')
    elif miss == 0:
        print('All grades provided')
    else:
        print('Invalid Data')

You probably would use status codes or other ways (like a return value to further process) to work with the information than just printing them. As an example with the print commands:

students['10003'].gradeStatus() # leads to: No grades at all

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM