EECS 298: Social Consequences of Computing

Lab 4

Task

For this lab, you will take the role of a professor processing final grades for a course. You will write a program to take student names and grades via user input, then calculate information about the grading curve and output the students’ assignment grades and semester grades in letter format. In this lab, you will recieve an introduction to Python input validation. You will also have practice implementing the randomized response mechanism to protect the students’ grade privacy. Finally, you will learn about the getattr() function.

lab4.py

First, download the files grades.csv, input.txt, input_bad_key.txt, and starter code lab4.py using the wget command:

wget https://raw.githubusercontent.com/eecs298/eecs298.github.io/main/files/grades.csv
wget https://raw.githubusercontent.com/eecs298/eecs298.github.io/main/files/input.txt
wget https://raw.githubusercontent.com/eecs298/eecs298.github.io/main/files/input_bad_key.txt
wget https://raw.githubusercontent.com/eecs298/eecs298.github.io/main/labs/lab4.py

In grades.csv, you will see grade and student ID information for 40 students. Information about each column is given in the constructor of the SemesterGrade class.

You will implement functions in two classes in lab4.py, SemesterGrade and StudentGrades, as follows:

In the main branch, you will first create a StudentGrades object and pass in the file path to grades.csv. Then, create a while True loop where you read in student_id and assignment inputs from the console with the following prompt.

[!TIP] Use the input function

Enter a student ID to return a semester grade:
>

After reading in a student_id, call query_student_grade_rr(student_id) and print out the following output

Student ID: XXXXXX, Semester Grade: X

Wrap your code in a try block and except Exception as e and print out e and break the loop if an exception is rasied in query_student_grade_rr(student_id). See the tips below for an example of handling exception in try/except blocks.

Example output

When running lab4.py on input.txt you should expect the following output:

$ python3 lab4.py < input.txt
Enter a student ID to return a semester grade:
Student ID: 543584, Semester Grade: C
Enter a student ID to return a semester grade:
Student ID: 263174, Semester Grade: B
Enter a student ID to return a semester grade:
Student ID: 908486, Semester Grade: C
Enter a student ID to return a semester grade:
Student ID: 591245, Semester Grade: F
Enter a student ID to return a semester grade:
End of queries.

When running lab4.py on input_bad_key.txt you should expect the following output:

$ python3 lab4.py < input_bad_key.txt
Enter a student ID to return a semester grade:
Student ID: 723068, Semester Grade: B
Enter a student ID to return a semester grade:
Student ID: 212583, Semester Grade: B
Enter a student ID to return a semester grade:
Student ID: 108978, Semester Grade: B
Enter a student ID to return a semester grade:
Student ID: 263174, Semester Grade: F
Enter a student ID to return a semester grade:
Student ID not found.

Turn in lab4.py to the Gradescope assignment when you’re done.

Tips

Input

To prompt the user for console input, use the input() function. The program will pause until the user hits the return key in the console, and then the function will return the user’s input as a string.

Error handling and Exceptions

Especially when dealing with user input, one might wish to handle potential errors arising in code. Since Python is a dynamically typed language, one example of such a case is handling when one’s code attempts to cast a variable to a type that it cannot be cast to. You can handle these situations with try and except blocks as shown:


def a_function(arg1: str):

    if not isinstance(arg1, str):
        raise Exception("arg1 should be of type str")
    else:
      print(arg1)
if __name__ == "__main__":
    try:
        string = "ABC"

        a_function(string)  

    except Exception as e: # This code gets executed when an Exception is raised
        print(e) # Output: arg1 should be of type str

np.random.uniform()

When using numpy functions, we first need to import numpy as follows

import numpy as np

Recall that the as keyword lets us rename the import to use in our program.

We will use the numpy function random.uniform() to sample a point from the range [0,1) uniformly at random. We can then use that value to simulate probabalistic events like, say, a fair coin flip.

import numpy as np

coin_toss = np.random.uniform() # generates a random float between 0 and 1

if coin_toss >= 0.5: # This happens 50% of the time 
    print("Heads")
else: # This happens 50% of the time
    print("Tails")

getattr()

We often find cases during runtime where we have the name of an attribute of an object and need to know the value of that object’s attribute. In this case we cannot directly access the attribute in the code. The getattr() function solves this problem.

class Student:
    def __init__(self, grade, name):
        self.grade = grade
        self.name = name

student1 = Student("A", "Tom")

attribute = input("Which attribute do you want to access: grade or name? ")

print(getattr(student1, attribute)) #If attribute = grade, the output is A. If attribute = name, the output is Tom