In my code, I'm trying to display the student with the highest grade in the class after calculating each grade received and their weight. For someone reason, I'm getting that the finalGrade is not defined. How would I display the student with the highest grade and their final grade as well?
def welcome():
print("Hello and Welcome to Top Students")
print("Our program lists your students and displays the highest of honors")
print("Let's get started\n")
def aveGrade():
quizGrade = int(input("What is the grade this student is receiving for their quiz?\n"))
partGrade = int(input("What is the grade this student is receiving for their prarticipation?\n"))
assignGrade = int(input("What is the grade this student is is receiving for their assignment?\n"))
finalGrade = ((quizGrade * .35) + (partGrade * .15) + (assignGrade * .50))
print("The final grade for this student is", finalGrade)
def main():
studentnames = ["Fred", "Daphne", "Velma", "Norville"]
for student in studentnames:
print("The current grade standing for", student, "are as follows:\n")
aveGrade()
print("The student with the highest final grade is", max(studentnames), "with a total of",max(finalGrade))
Variables only exist in scopes. In this case finalGrades is defined in the aveGrade() function and can only be accessed from within this function. Therefore your main function does not "know" about the finalGrade variable. You can declare finalGrade in the global scope and then asign the value to it in the function.
But the better solution would be to return the value from the function like this:
def aveGrade():
quizGrade = int(input("What is the grade this student is receiving for their quiz?\n"))
partGrade = int(input("What is the grade this student is receiving for their prarticipation?\n"))
assignGrade = int(input("What is the grade this student is is receiving for their assignment?\n"))
finalGrade = ((quizGrade * .35) + (partGrade * .15) + (assignGrade * .50))
print("The final grade for this student is", finalGrade)
return finalGrade #Changed
And then use it like this:
def main():
studentnames = ["Fred", "Daphne", "Velma", "Norville"]
for student in studentnames:
print("The current grade standing for", student, "are as follows:\n")
finalGrade = aveGrade() #Changed
print("The student with the highest final grade is", max(studentnames), "with a total of",max(finalGrade))
Addition to the comment:
Velma remains your highest student because your students and their final grade are not connected in any way. Currently you are just calculating and returning the final grade but the program does not know that it belongs to a student. max(studentnames) will always return Velma because in alphabetical order Velma is the highest value. Also max(finalGrade) won't do much because in each iteration of your for loop finalGrade is getting overwritten by the return value of aveGrade() and therefore isn't a list where a max value can be determined. One approach is to save the student and their final grade as a key value pair in a dictionairy
def main():
studentnames = ["Fred", "Daphne", "Velma", "Norville"]
studentGradesDic = {} #Added
for student in studentnames:
print("The current grade standing for", student, "are as follows:\n")
studentGradesDic[student] = aveGrade() #Changed
print("The student with the highest final grade is", list(studentGradesDic.keys())[list(studentGradesDic.values()).index(max(studentGradesDic.values()))], "with a total of",max(studentGradesDic.values())) #Changed
Related
I want my program to take any number of scores from any number of students, and run calculations on them.
student_number = 1
try:
score = int(input("Please enter Student " + str(student_number) + "'s score (-1: Exit): "))
except:
print("The score entered is not a number. Please enter it again.")
score = int(input("Please enter Student " + str(student_number) + "'s score (-1: Exit): "))
while score != -1:
try:
score = int(input("Please enter Student " + str(student_number) + "'s score (-1: Exit): "))
except:
print("The score entered is not a number. Please enter it again.")
score = int(input("Please enter Student " + str(student_number) + "'s score (-1: Exit): "))
more_student = input("Any more student? (Yes or No): ")
while more_student == "Yes":
student_number = student_number + 1
try:
score = int(input("Please enter Student " + str(student_number) + "'s score (-1: Exit): "))
except:
print("The score entered is not a number. Please enter it again.")
score = int(input("Please enter Student " + str(student_number) + "'s score (-1: Exit): "))
while score != -1:
score = int(input("Please enter Student " + str(student_number) + "'s score (-1: Exit): "))
more_student = input("Any more student? (Yes or No): ")
print("done")
Instead of print("done"), I want to somehow take every input I have received and be able to split it up by student, example output:
Student _ has 4 scores. Their average score is _.
Student _ has 3 scores. Their average score is _.
i'd use a dictionary i guess ? This will allow to collect data for each student, namely.
scores = {}
student = input("Student ? ") # Ask for student
if(student not in scores.keys()): # Create new student if necessary
scores[student] = []
score = int(input("Score ? ")) # Generate & store score for the student
scores[student].append(score)
Then to compute for each student the mean of the scores ... So many possibilities. The easiest one to me:
for student, score_list in scores.items():
nb_scores = len(score_list)
mean_score = sum(score_list)/len(score_list)
print("Student {} had {} scores, with a mean of {}". format(student, nb_scores, mean_score))
I'd just finished typing this up for another question of yours that got deleted -- it looks like the same basic problem as this one.
The approach in a nutshell (as I see the accepted answer to this version of the question is already doing) is to use two nested loops, breaking them when it's time to go to the outer loop.
scores = []
while True:
scores.append([])
while True:
try:
score = int(input(
f"Please enter Student {len(scores)}'s score (-1: Exit): "
))
if score == -1:
break
scores[-1].append(score)
except ValueError:
print("The score entered is not a number. Please enter it again.")
if input("Any more student? (Yes or No): ").lower() != "yes":
break
print(scores)
Please enter Student 1's score (-1: Exit): 78
Please enter Student 1's score (-1: Exit): 34
Please enter Student 1's score (-1: Exit): -1
Any more student? (Yes or No): yes
Please enter Student 2's score (-1: Exit): 45
Please enter Student 2's score (-1: Exit): -1
Any more student? (Yes or No): No
[[78, 34], [45]]
I included two infinite loops that breaks when -1 is entered. A hashmap is used where every Student ID is a key and is initialized with an empty array that stores the marks as the second loop executes itself.
marks = {}
while True:
i = int(input("Enter Student ID or press -1 to exit"))
if i == -1:
break
else:
marks[i] = []
while True:
x = int(input("Enter Mark or press -1 to exit"))
if x!=-1:
marks[i].append(x)
else:
break
for i in marks.keys():
count = len(marks[i])
avg = sum(marks[i])/count
print("Student {} has {} scores. Their average is {}".format(i, count, avg))
Where am I going wrong, the first part does exactly what I want. I put the first student in with scores it converts and averages but after repeat, it combines the lists and averages ofoutput all subsequent students.
def determine_grade(score):
if (score > 89):
return "A"
elif (score > 79):
return "B"
elif (score > 69):
return "C"
elif (score > 59):
return "D"
elif (score <= 59):
return "F"
def calc_average(test_scores):
total = 0
for i in range(len(test_scores)):
total = total + test_scores[i]
return total/int(len(test_scores))
def main():
repeat="yes"
test_scores = []
while repeat.lower() == "yes":
student = input("\nEnter student name: ")
for i in range(2):
score = round(float(input("Enter score: ")))
test_scores.append(score)
average_score = calc_average(test_scores)
print("\nStudent Name: ", student)
for i in range(len(test_scores)):
print("Score: ",test_scores[i], "Grade: ",determine_grade(test_scores[i]))
print("Average: ", average_score, "Student: ",student)
repeat = input("\nEnter anther student? yes or no: ")
main()
The thing that is wrong with this piece of code is that when you finished collecting info from one student the info is still left in the list, and was mixed up with another student's info
def main():
repeat="yes"
test_scores = []
while repeat.lower() == "yes":
test_scores.clear()
student = input("\nEnter student name: ")
for i in range(2):
score = round(float(input("Enter score: ")))
test_scores.append(score)
average_score = calc_average(test_scores)
print("\nStudent Name: ", student)
for i in range(len(test_scores)):
print("Score: ",test_scores[i], "Grade: ",determine_grade(test_scores[i]))
print("Average: ", average_score, "Student: ",student)
repeat = input("\nEnter another student? yes or no: ")
main()
You need to clear the list before collecting again.
After this line:
while repeat.lower() == "yes":
put:
print(test_scores)
Run the script and enter marks for a couple of students.
I think you will see why it is summing all the students marks in one go.
By the way, sum(test_scores) will add up the elements of test_scores for you. No need
for a loop. Also try out:
for score in test_scores:
print(score)
In general, when you are tempted to write
for i in range(len(things)):
followed by
things[i]
inside the loop, it is usually easier to write
for thing in things:
do_something_with(thing)
Your code will be shorter, more readable and more efficient.
Replace your main fucntion with this one:
def main():
repeat="yes"
while repeat.lower() == "yes":
test_scores = [] # Inside the while loop so it is new every time
student = input("\nEnter student name: ")
for i in range(2):
score = round(float(input("Enter score: ")))
test_scores.append(score)
average_score = calc_average(test_scores)
print("\nStudent Name: ", student)
for i in range(len(test_scores)):
print("Score: ",test_scores[i], "Grade: ",determine_grade(test_scores[i]))
print("Average: ", average_score, "Student: ",student)
repeat = input("\nEnter anther student? yes or no: ")
I'm working on a project/exercise where I need to use OOP in Python to create a Grade Book. I've been learning Python and working with 3.8.3 for about 6 weeks now, so I'm still fairly new. The grade book has a basic menu where you can add an assignment, quiz, and final exam grades. I must use a class with an empty list for both the quiz and assignment grades. I did a rough draft of the code after reading a bit on OOP, and managed to get the class to function without using attributes and only one method as below:
class GradeBook:
def main_function():
quiz_scores = []
assignment_scores = []
while True:
try:
quiz_grade = float(input('Please enter a grade for the quiz, or press Enter to stop adding grades: '))
quiz_scores.append(quiz_grade)
except:
break
while True:
try:
assignment_grade = float(input('Please enter a grade for the assignment, or press Enter to stop adding grades: '))
assignment_scores.append(assignment_grade)
except:
break
print (quiz_scores)
print (assignment_scores)
print ('time for totals and averages')
quiz_total = sum(quiz_scores)
assignment_total = sum(assignment_scores)
print ('quiz total ' + str(quiz_total))
print ('assign total ' + str(assignment_total))
if len(quiz_scores) > 0:
quizScoreAverage = sum(quiz_scores)// len(quiz_scores)
else:
quizScoreAverage = 0
if len(assignment_scores) > 0:
assignmentScoreAverage = sum(assignment_scores) // len(assignment_scores)
else:
assignmentScoreAverage = 0
print ('quiz average ' + str(quizScoreAverage))
print ('assign average ' + str(assignmentScoreAverage))
GradeBook.main_function()
Here is where I am running into my issues. I need to split the code up into several methods/functions, one for quiz scores, one for assignment scores, one that will store the final exam score and do nothing more, and one for getting the current grade/average. I've been searching and searching but have hit a wall. The code works up until I attempt to append the user's input to the list in the class. Again this is just a rough draft of the code as follows:
class GradeBook:
# Need this at attribute level for all instances to acccess as there will be an instance the pulls the list to calculate overall grade
assignment_scores = []
# quiz_scores = [] ### - This is the other list that will also be used for the grade
def assignGrade(self, score):
self.score = score
self.assignment_scores.append(score)
#####################################################
'''
This will be a duplicate of the above code but will use values to store quiz grades instead
def quizGrade(self, score):
self.score = score
self.quiz_scores.append(score)
'''
#####################################################
while True:
try:
assignment_grade = float(input('Please enter a grade for the assignment, or press Enter to stop adding grades: '))
# Program works just fine up until this point. My issue is here. Trying to feed the user input into the class instance
# to update the class list that is stored as an attribute. Instead of appending it seems to throw an error,
# because it doesn't continue the try loop for input and after the break when the list is printed, no values are shown
assignment_grade = GradeBook.assignGrade(assignment_grade) # <------- THIS IS THE PROBLEM CHILD OF MY CODING
except:
break
#####################################################
''' This block will be used to get input for the quiz grade to append to quiz scores list
while True:
try:
quiz_grade = float(input('Please enter a grade for the assignment, or press Enter to stop adding grades: '))
quiz_grade = GradeBook.quizGrade(quiz_grade) #not sure if this is right?
except:
break
'''
#####################################################
I guess I'm just not getting a good grasp on the whole idea of sending information from one instance to another. Any input is greatly appreciated. My plan is once it all gets figured out I just need to plug in the code to my final draft here:
class GradeBook:
# Initializes empty list to store quiz and assignment grades
quiz_scores = []
assignment_scores = []
#####################################################
def quizScore(self, score)
# lines of code to append user input to quiz list for reference in class
#####################################################
def assignScore(self, score)
# lines of code to append user input to assignment list for reference in class
#####################################################
def finalScore(self, score)
# line of code to store the final exam grade for reference in the class
#####################################################
def currentAverage(self)
if len(self.assignment_scores) > 0:
assignmentScoreAverage = sum(self.assignment_scores) // len(self.assignment_scores)
else:
assignmentScoreAverage = 0
if len(self.quiz_scores) > 0:
quizScoreAverage = sum(self.quiz_scores) // len(self.quiz_scores)
else:
quizScoreAverage = 0
currentGrade = (0.4 * self.final_grade) + (0.3 * quizScoreAverage) + (0.3 * assignmentScoreAverage)
return currentGrade
#####################################################
print('''
Grade Book
0: Exit
1: Enter assignment grade
2: Enter quiz grade
3: Enter final exam grade
4: Display current grade
''')
while True:
try:
selection = int(input('Please enter a choice: '))
if selection == 0:
quit
elif selection == 1:
while True:
try:
assignment_grade = float(input('Please enter a grade for the assignment, or press Enter to stop adding grades: '))
GradeBook.assignScore(assignment_grade)
except:
break
elif selection == 2:
while True:
try:
quiz_grade = float(input('Please enter a grade for the assignment, or press Enter to stop adding grades: '))
GradeBook.quizScore(quiz_grade)
except:
break
elif selection == 3:
while True:
try:
final_grade = float(input('Please enter a grade for the assignment, or press Enter to stop adding grades: '))
GradeBook.finalScore(final_grade)
except:
break
elif selection == 3:
final_grade = float(input('Please enter a grade for the final exam: '))
if isdigit(final_grade)
GradeBook.finalScore(final_grade)
else:
print('Please check your input and try again.')
elif selection == 4:
print(GradeBook.currentAverage())
else:
print('Please check your input and try again.')
continue
(Please, use snake case for all your code, including methods. Camel case should only be used for classes) In python I would recommend creating a module(file) without class for your main function. You are using the assignGrade method as a class method. Actually, you never even created an instance of your class! To create an instance, you should call the class as follows:
my_grades = GradeBook()
Now, my_grades is "a variable"(an instance) that contains all the properties(attributes) you defined for your class. You can access them as follows:
my_grades.assignment_scores
Your loop will fail because you have not passed the self argument to the function you pointed as the problem. In python, all instance methods start with the self argument, but it will be the variable(instance) before the dot. So, you should call it from an instance of your class and not from the class itself. Using the one I created from the first example, you can change the line to:
my_grades.assignGrade(assignment_grade)
That should do.
Instead of creating and calling a main_function, in the module add the following:
if __name__ == '__main__':
... # Create your instances and manipulate them here
So following the guidelines that were provided to us, as well as the example inputs, I have the program working as intended. Since this was just an introduction class, we didn't get into using methods in separate files, so I did not use:
if __name__ == '__main__':
However, I would like any comments on it like readability and other coding practices. Working code below:
# Programmed by thelastesquire92
# Programming Assignment 7 - Grade Book App
# SEC290.B2.32789
'''
Program that focuses on Object Oriented Programming.
The user is presented with simple text menu, and following
input prompts they are allowed to enter grades for quizzes,
assignments, and a final exam. The program then calculates
the average grade based off of these inputs.
'''
class GradeBook:
# Initializes empty list for quiz and assignment grades, sets default final score to 0
quiz_scores = []
assignment_scores = []
final_exam_score = 0
#####################################################
# Adds grade input to list of quiz scores
def quiz_score(self, score):
self.quiz_scores.append(score)
#####################################################
# Adds grade input to list of assignment scores
def assignment_score(self, score):
self.assignment_scores.append(score)
#####################################################
# Updates value of final exam score
def final_score(self, score):
GradeBook.final_exam_score = score
#####################################################
# Calculates current grade average
def current_average(self):
if len(GradeBook.assignment_scores) > 0:
assignment_score_average = sum(GradeBook.assignment_scores)\
// len(GradeBook.assignment_scores)
else:
assignment_score_average = 0
if len(GradeBook.quiz_scores) > 0:
quiz_score_average = sum(GradeBook.quiz_scores)\
// len(GradeBook.quiz_scores)
else:
quiz_score_average = 0
current_grade = (0.4 * GradeBook.final_exam_score)\
+ (0.3 * quiz_score_average)\
+ (0.3 * assignment_score_average)
return current_grade
#####################################################
# Prints out the menu for user
menu = ('''
Grade Book
0: Exit
1: Enter assignment grade
2: Enter quiz grade
3: Enter final exam grade
4: Display current grade
''')
print(menu)
#####################################################
# Main body of program that loops until user selects option to exit
while True:
# Creates instance of GradeBook
my_grades = GradeBook()
try:
selection = int(input('\nPlease enter a choice: '))
#####################################################
# Option 0 that exits the program
if selection == 0:
break
#####################################################
# Option 1 that allows input for assignment grades
elif selection == 1:
while True:
try:
assignment_grade = float(input('\nPlease enter a grade for the assignment: '))
my_grades.assignment_score(assignment_grade)
break
except:
print('\nPlease check your input and try again.')
continue
#####################################################
# Option 2 that allows input for quiz grades
elif selection == 2:
while True:
try:
quiz_grade = float(input('\nPlease enter a grade for the quiz: '))
my_grades.quiz_score(quiz_grade)
break
except:
print('\nPlease check your input and try again.')
continue
#####################################################
# Option 3 that allows input for final exam grade
elif selection == 3:
while True:
try:
final_grade = float(input('\nPlease enter a grade for the final exam: '))
my_grades.final_score(final_grade)
break
except:
print('\nPlease check your input and try again.')
continue
#####################################################
# Option 4 that displays current grade average
elif selection == 4:
average = my_grades.current_average()
print('\nYour current grade average is: ' + str(average))
else:
print('\nPlease check your input and try again.')
continue
except:
print('\nPlease check your input and try again.')
print(menu)
continue
python 3.3.3
I am trying to write a program for class and I am lost. Here is what I need to do.
I need to calculate an average per student based on grades entered.
I need to calculate a class average.
if a student enters a grade of -1 input of grades stop.
need to print a message with each students grade.
the students grade should show a numeric grade and a letter grade.
the message will be based off of the students letter grade.
how do i collect and store students name and test grades.
so that i can output it all at once to where it will show the students name.
thier numeric average, a letter grade based off that average,
and a statement based off the letter grade they recieved?
heres the code i have so far:
def main():
another_student = 'y'
while another_student == 'y' or another_student == 'Y':
student_average()
print()
another_student = input('do you have another student to enter (y/n) ? ')
while another_student == 'n' or another_student == 'N':
student_average_list()
class_average()
break
def student_average():
total = 0.0
print()
student_name = input('what is the students name? ')
print()
print()
print(student_name)
print('-------------------')
number_of_tests = int(input('please enter the number of tests : '))
for test_num in range(number_of_tests):
print('test number', test_num + 1, end='')
score = float(input(': '))
total += score
student_average = total / number_of_tests
print ()
print(student_name,"'s average is : ",student_average, sep='')
def student_average_list():
print ('kahdjskh')
def class_average():
print ('alsjd')
main()
I think this is close to what you're basically looking for. It defines aStudentclass to make data storage and processing a little easier to manage.
class Student(object):
def __init__(self, name):
self.name, self.grades = name, []
def append_grade(self, grade):
self.grades.append(grade)
def average(self):
return sum(self.grades) / len(self.grades)
def letter_grade(self):
average = self.average()
for value, grade in (90, "A"), (80, "B"), (70, "C"), (60, "D"):
if average >= value:
return grade
else:
return "F"
def main():
print()
print('Collecting class student information')
a_class = [] # "class" by itself is a reserved word in Python, avoid using
while True:
print()
print('{} students in class so far'.format(len(a_class)))
another_student = input('Do you have another student to enter (y/n) ? ')
if another_student[0].lower() != 'y':
break
print()
student_name = input('What is the student\'s name? ')
a_class.append(Student(student_name))
print()
print('student :', student_name)
print('-------------------')
number_of_tests = int(input('Please enter the number of tests : '))
for test_num in range(1, number_of_tests+1):
print('test number {}'.format(test_num), end='')
score = float(input(' : '))
if score < 0: # stop early?
break
a_class[-1].append_grade(score) # append to last student added
print_report(a_class)
def print_report(a_class):
print()
print('Class Report')
print()
for student in sorted(a_class, key=lambda s: s.name):
print('student: {:20s} average test score: {:3.2f} grade: {}'.format(
student.name, student.average(), student.letter_grade()))
print()
print('The class average is {:.2f}'.format(class_average(a_class)))
def class_average(a_class):
return sum(student.average() for student in a_class) / len(a_class)
main()
You need to keep a list of marks for the whole class. student_average function is doing too many things. Maybe make a function get_student_marks that just returns the list of a student's marks. You'd need an average function to compute the average of a list, which you could use for both student average and class average. Good luck!
I have been trying to get this program to work, and it runs but once I got it to run I uncovered this problem. Right now it asks for gradePoint and credit hours and prints out a GPA like it is supposed to, but I can type anything in gradePoint and it will spit out a value. What I want is gradePoint to only work if the user types in a number between 0.0-4.0.
I was thinking of a loop of some sort, like an if loop but is there an easier way (or a preferred way) to do this?
Here's the code:
def stu():
stu = Student
class Student:
def __init__(self, name, hours, qpoints):
self.name = name
self.hours = float(hours)
self.qpoints = float(qpoints)
def getName(self):
return self.name
def getHours(self):
return self.hours
def getQpoints(self):
return self.qpoints
def getStudent(infoStr):
name, hours, qpoints = infoStr.split("\t")
return Student(name, hours, qpoints)
def addGrade(self, gradePoint, credits):
self.qpoints = gradePoint * credits
self.hours = credits
self.gradePoint = float(gradePoint)
self.credits = float(credits)
def gpa(self):
return self.qpoints/self.hours
def main():
stu = Student(" ", 0.0, 0.0)
credits = int(input("Enter Credit Hours "))
gradePoint = float(input("Enter Grade Point"))
if gradePoint > 4.0:
print("Please enter a Grade Point that is less then 4.")
stu.addGrade(gradePoint,credits)
output = stu.gpa()
print("\nStudent GPA is: ", output)
main()
This is the shell printout(I know the grade point is repeated in the GPA, this is for a class and we were supposed to use a skeleton program and change some things):
Enter Credit Hours 4
Enter Grade Point 3.5
Student GPA is: 3.5
Enter Credit Hours 12
Enter Grade Point 3.2
Student GPA is: 3.2
Thanks!
EDIT: I just did an if loop as suggested in the comments and it worked somewhat in that it printed out what I wanted but didn't make it stop and wait for the correct input. I'm not exactly sure how to get it to do that.
Here is the new print from the shell:
Enter Credit Hours 4
Enter Grade Point 3.5
Student GPA is: 3.5
Enter Credit Hours 4
Enter Grade Point 4.5
Please enter a Grade Point that is less then 4.
Student GPA is: 4.5
You can check if user input meet your requirements and throw an exception if not. This will make the program log an error message and stop on invalid user input.
The most basic way to do this is to use an assert statement:
def main():
stu = Student(" ", 0.0, 0.0)
credits = int(input("Enter Credit Hours "))
assert credits > 0 and credits < 4, "Please enter a number of Credit Hours between 0 and 4."
If you wish the application to keep prompting the user until a valid input is entered, you will need at least one while loop.
For exemple:
def main():
stu = Student(" ", 0.0, 0.0)
while True:
credits = int(input("Enter Credit Hours "))
if credits > 0 and credits < 4:
break
else:
print("Please enter a number of Credit Hours between 0 and 4")
while True:
gradePoint = float(input("Enter Grade Point"))
if gradePoint <= 4.0:
break
else:
print("Please enter a Grade Point that is less then 4.")
stu.addGrade(gradePoint,credits)
output = stu.gpa()
print("\nStudent GPA is: ", output)
Create a function that gathers a valid float from the user within a range:
def getValidFloat(prompt, error_prompt, minVal, maxVal):
while True:
userInput = raw_input(prompt)
try:
userInput = float(userInput)
if minVal <= userInput <= maxVal:
return userInput
else: raise ValueError
except ValueError:
print error_prompt
And then use like this:
gpa = getValidFloat(
"Enter Grade Point ",
"You must enter a valid number between 1.0 and 4.0",
1,
4)
The output would look something like this:
Enter Grade Point 6.3
You must enter a valid number between 1.0 and 4.0
Enter Grade Point 3.8