I'm new to python, taking my first class in it right now, only about 4 weeks in.
The assignment is to calculate test average and display the grade for each test inputted.
Part of the assignment is to use a function to calculate the average as well as deciding what letter grade to be assigned to each score.
As I understand it, functions are supposed to help cut down global variables.
My question is this: how do I condense this code?
I don't know how to use a function for deciding letter grade and then displaying that without creating a global variable for each grade that has been inputted.
If you notice any redundancy in my code, I would appreciate a heads up and a little lesson on how to cut that out. I can already smell the mark downs I will get if I turn this in as is...
def main():
grade1=float(input( "Enter score (0-100):"))
while (grade1 <0 or grade1 >100 ):
if grade1 <0 or grade1 >100:
print("Please enter a valid grade")
grade1=float(input( "Enter score (0-100):"))
grade2=float(input( "Enter score (0-100):"))
while (grade2 <0 or grade2 >100 ):
if grade2 <0 or grade2 >100:
print("Please enter a valid grade")
grade2=float(input( "Enter score (0-100):"))
grade3=float(input( "Enter score (0-100):"))
while (grade3 <0 or grade3 >100 ):
if grade3 <0 or grade3 >100:
print("Please enter a valid grade")
grade3=float(input( "Enter score (0-100):"))
grade4=float(input( "Enter score (0-100):"))
while (grade4 <0 or grade4 >100 ):
if grade4 <0 or grade4 >100:
print("Please enter a valid grade")
grade4=float(input( "Enter score (0-100):"))
grade5=float(input( "Enter score (0-100):"))
while (grade5 <0 or grade5 >100 ):
if grade5 <0 or grade5 >100:
print("Please enter a valid grade")
grade5=float(input( "Enter score (0-100):"))
total=grade1+grade2+grade3+grade4+grade5
testAverage=calcAverage(total)
eachGrade1=determineGrade(grade1)
eachGrade2=determineGrade(grade2)
eachGrade3=determineGrade(grade3)
eachGrade4=determineGrade(grade4)
eachGrade5=determineGrade(grade5)
print("\nTest #1 grade:", (eachGrade1))
print("Test #2 grade:", (eachGrade2))
print("Test #3 grade:", (eachGrade3))
print("Test #4 grade:", (eachGrade4))
print("Test #5 grade:", (eachGrade5))
print("\nTest average:", (testAverage),("%"))
def calcAverage(total):
average=total/5
return average
def determineGrade(grade):
if grade >=90:
return "A"
elif grade >=80:
return "B"
elif grade >=70:
return "C"
elif grade >=60:
return "D"
else:
return "F"
I won't refactor your whole code, but here's a few pointers:
First of all, you need a function to get the user input, let's call it get_score. I won't go into the details here because there's an excellent resource on how to write a function for that here: Asking the user for input until they give a valid response. That function should return a float or integer, so don't forget that input (assuming you are using Python 3) returns a string which you have to cast to int or float manually.
To get a list of n scores, I propose the function:
def get_n_scores(n):
return [get_score() for _ in range(n)]
The stuff in the square brackets is a list comprehension and equivalent to:
scores = []
for _ in range(n):
scores.append(get_score())
Use this code instead if you are not comfortable with the comprehension (don't forget to return result).
The variable name _ is commonly used to indicate a temporary value that is not used (other than for iteration).
You can avoid declaring grade1 ... grade5 by calling all_scores = get_n_scores(5), which will return a list with the user input. Remember that indexing is zero-based, so you'll be able to access all_scores[0] ... all_scores[4].
Instead of hardcoding total, you can just apply the built in sum function: total = sum(all_scores), assuming all_scores holds integers or floats.
Finally, you can determine the grade for each score by applying your function determineGrade to every score in all_scores. Again, you can use a comprehension:
all_grades = [determineGrade(score) for score in all_scores]
or the traditional:
all_grades = []
for score in all_scores:
all_grades.append(determineGrade(score))
The other stuff looks okay, except that in order to print the grade you can just loop over all_grades and print the items. It's up to you if you want to write further functions that wrap a couple of the individual function calls we're making.
In general, always avoid repeating yourself, write a function instead.
I'll write is as below:
def get_grade():
while(True):
grade = float(input("Enter score (0-100):"))
if grade >= 0 and grade <= 100:
return grade
print("Please enter a valid grade!")
def get_average(sum_val, counter):
return sum_val/counter
def determine_grade(grade):
if grade >=90:
return "A"
elif grade >=80:
return "B"
elif grade >=70:
return "C"
elif grade >=60:
return "D"
else:
return "F"
test_num = 5
sum_val = 0
result = {}
for i in range(test_num):
grade = get_grade()
result[i] = determine_grade(grade)
sum_val += grade
for key in result:
print ("Test %d Grade is %s" % (key+1, result[key]))
avg = get_average(sum_val, test_num)
print ("Average is %d" % avg)
Works like this:
>>> ================================ RESTART ================================
>>>
Enter score (0-100):89
Enter score (0-100):34
Enter score (0-100):348
Please enter a valid grade!
Enter score (0-100):34
Enter score (0-100):90
Enter score (0-100):85
Test 1 Grade is B
Test 2 Grade is F
Test 3 Grade is F
Test 4 Grade is A
Test 5 Grade is B
Average is 66
>>>
Related
Currently doing a college assignment where we need to input and add 3 different scores.
The Scores must be not be less than 0 or greater than 10, and they can only be in multiples of 0.5. It's the latter part I'm having trouble with.
How do I tell the program to give an error if the input isn't a multiple of 0.5?
score1 = float(input("Please input the first score: ")
if score1 <0 or score1 >10:
score1 = float(input("Error! Scores can only be between 0 and 10.\n Please input Score 1 again: "))
elif score1
One way to do this is to use a while loop:
score1 = float(input("Please input the first score: ")
# while loop will keep asking for correct input if the input does not satisfy the requirements
while score1 <0 or score1 >10 or not (score1%0.5)== 0.0:
score1 = float(input("Error! Scores can only be between 0 and 10 and in multiples of 0.5.\n Please input Score 1 again: ")
print(score1, "passes all the tests")
or alternatively, you could raise an error statement if you'd like:
score1 = float(input("score: "))
if score1<0 or score1>10 or not (score1%0.5)==0.0:
raise BaseException("Error! the input score1 must be between 1 and 10 and a multiple of 0.5")
print(score1, "passes all the tests")
Nested if statement comes into play here. First it will check the condn is score>0 and score<10 then the next if statement of checking multiple statement comes to play. Use loop for taking input back to back until condn not met.
score = float(input("Enter score"))
if score>0 and score<10:
if (score*10)%5 == 0:
print(" Score is a Multiple of 0.5")
else:
print("Score is Not multiple of 0.5")
else:
print("Error! Scores can only be between 0 and 10")
`
The Question
Write a program that asks the user to enter their name and grades for all the courses they took this
semester. Check that the name is composed of only letters and that each grade entry is composed of
numbers only. When the user has entered all their grades, they may enter -1 to indicate they are done.
Calculate the average grade and display that to the user.
Sample given to me
Enter your name: Sar#
Please enter a valid name.
Enter your name: sara
Enter your grade for course 1: 90
Enter your grade for course 2: 90s
Please enter a valid grade.
Enter your grade for course 2: 80
Enter your grade for course 3: 70
Enter your grade for course 4: 60
Enter your grade for course 5: -1
Sara, your average grade for 4 courses this semester is 75.0. Well done!
My progress
count=0
sum=0
name = input("Enter your name: ")
while name.isalpha()==False:
print("Please enter a valid name.")
name = input("Enter your name: ")
grade = int(input("Enter your grade for course "+ str(count+1)+": "))
grade == 1
while grade!=-1:
grade = str(grade)
while grade.isnumeric()==False:
print("Please enter a valid grade.")
grade = input("Enter your grade for course "+ str(count+1)+": ")
grade =int(grade)
count+=1
sum+=grade
grade = int(input("Enter your grade for course "+ str(count+1)+": "))
avg = sum/count
if avg>60:
print(name.capitalize(),", your average grade for",count,"courses this semester is",avg,". Well done!")
else:
print(name.capitalize(),", your average grade for",count,"courses this semester is",avg,". Please do better.")
I get an int error. though I know why I get the error but have no other way to solve this problem. Please help!
You can use try except
Like this:
count=0
sum=0
name = input("Enter your name: ")
while name.isalpha()==False:
print("Please enter a valid name.")
name = input("Enter your name: ")
grade = 1
while grade!=-1:
try:
grade = int(input("Enter your grade for course "+ str(count+1)+": "))
if grade == -1: break
count+=1
sum+=grade
except:
print("Please enter a valid grade.")
avg = sum/count
if avg>60:
print(name.capitalize(),", your average grade for",count,"courses this semester is",avg,". Well done!")
else:
print(name.capitalize(),", your average grade for",count,"courses this semester is",avg,". Please do better.")
I assume you got an int error after entering a non-numeric value as your grade. You convert the grade to an int when you define it without checking if it's a numeric value or not. This will raise an exception, you can avoid it by using try/except or first checking if grade is numeric.
Your while grade.isnumeric()==False: is failing when user enters nothing. It passes through an empty string and in line
grade = int(input("Enter your grade for course "+ str(count+1)+": "))
it tries to evaluate it as int although it can't since its an empty string.
You have several things wrong with this homework assignment.
Here are some suggestions:
Append to a list grades =[] rather than a running grade that is initialized with a '1'. You don't want the '1' to be part of your average.
Use a try/except clause to validate the user input.
Compute the average on the list after you exit the while loop.
def calc_average(a,b,c,d,f):#function used to calculate average
return (a+b+c+d+f)//5
def determine_grade(test_score):#function used to determine letter grade
if gradeAverage > 89:
return "A"
elif gradeAverage > 79:
return "B"
elif gradeAverage > 69:
return "C"
elif gradeAverage > 59:
return "D"
else:
return "F"
test1 = float(input("Please enter test score for test1: "))#prompt user to enter grade
test2 = float(input("Please enter test score for test2: "))#prompt user to enter grade
test3 = float(input("Please enter test score for test3: "))#prompt user to enter grade
test4 = float(input("Please enter test score for test4: "))#prompt user to enter grade
test5 = float(input("Please enter test score for test5: "))#prompt user to enter grade
gradeAverage = calc_average(test1, test2, test3, test4, test5)#variable
finalgrade = determine_grade(gradeAverage)#variable
print(finalgrade)#display grade
print(gradeAverage)display grade letter
This is a problem in the "starting out with Python" book, I am supposed to calculate the average grade of 5 test scores and give a letter grade. My problem is, I wonder if I need the variables or not. If there is a better way I would like to know.
You can use for loops and lists to eliminate some variables and also generalize a bit:
def calc_average(grades): #function used to calculate average, now takes a list
return sum(grades)//len(grades)
grades = []
number_of_tests = int(input("input the total number of test results >>"))
for i in range(1, number_of_tests+1):
g = int(input("input grade " + str(i) +" >>"))
grades.append(g)
avg = calc_average(grades)
print(avg)
I would explain everything in detail, but I am sure your text book will soon enough tell you about "for loops", "lists", and so on. They usually start slow, and let you do unnecessary work so you can get used to the basics. Keep on reading m8 :)
(Or watch this video, in my opinion this is one of the best beginners guides out there: https://youtu.be/rfscVS0vtbw)
Please allow me to share a few comments:
The function determine_grade(test_score) takes in a parameter test_score, and should be using this parameter to determine the grade, instead of the global parameter gradeAverage. So your code should be:
def determine_grade(test_score):#function used to determine letter grade
if test_score > 89:
return "A"
elif test_score > 79:
return "B"
elif test_score > 69:
return "C"
elif test_score > 59:
return "D"
else:
return "F"
The calculation for average should not be a floor division (a+b+c+d+f)//5. This floor division formula outputs only the integer value and ignores the decimals behind. So the formula should be (a+b+c+d+f)/5.
A for loop would be elegant, and avoiding repeated codes. Then a list test_list could be used to store the test scores and be passed to the function calc_average to calculate the average.
The final code should look like this:
def calc_average(test_list): #function used to calculate average
return sum(test_list)/len(test_list)
def determine_grade(test_score): #function used to determine letter grade
if test_score > 89:
return "A"
elif test_score > 79:
return "B"
elif test_score > 69:
return "C"
elif test_score > 59:
return "D"
else:
return "F"
n = 5
test_list = []
for i in range(n):
score = float(input("Please enter test score for test{}: ".format(i+1))) #prompt user to enter grade
test_list.append(score)
gradeAverage = calc_average(test_list) #variable
finalgrade = determine_grade(gradeAverage) #variable
print(finalgrade) #display grade
print(gradeAverage) #display grade letter
Output
Please enter test score for test1: 66
Please enter test score for test2: 77
Please enter test score for test3: 88
Please enter test score for test4: 86
Please enter test score for test5: 69
C
77.2
desired outcome:
Enter a test score (-99 to exit): 55
Enter a test score (-99 to exit): 77
Enter a test score (-99 to exit): 88
Enter a test score (-99 to exit): 24
Enter a test score (-99 to exit): 45
Enter a test score (-99 to exit): -99
55 77 88 24 45
P P P F F
Process finished with exit code 0
The code so far: (works except for Pass fail assignment)
Python Program to ask user to input scores that are added to a list called scores. Then prints under that score P for Pass F for fail.
scores = [] #list is initialized
while True:
score = int(input("Enter a test score (-99 to exit): "))
if score == -99:
break
scores.append(score)
def print_scores(): #accepts the list and prints each score separated by a space
for item in scores:
print(item, end = " ") # or 'print item,'
print_scores() # print output
def set_grades(): #function determines whether pass or fail
for grade in scores:
if score >= 50:
print("P")
else:
print("F")
print(set_grades)
You're thinking along the right lines, but you need to run through your program from the top and make sure that you're getting your reasoning right.
Firstly, you've written the program to print out all the scores before you get to checking if they're passes, so you'll get a list of numbers and then a list of P/F. These need to happen together to display properly.
Also, make sure that you keep track of what variable is what; in your last function, you attempt to use 'score', which doesn't exist anymore.
Finally, I'm not sure what exactly you're asking with %d or %s, but you may be looking for named arguments with format(), which are shown below.
scores = [] #list is initialized
while True:
score = int(input("Enter a test score (-99 to exit): "))
if score == -99:
break
scores.append(score)
for item in scores:
if item >= 50:
mark = 'P'
else:
mark = 'F'
print('{0} {1}'.format(item, mark))
I believe this is what you're looking for.
I wrote a grade calculator where you put a float in and get a grade based on what you scored. The problem I have is that I belive I need a float(input... But that becomes an error if you write letters in the box...
def scoreGrade():
"""
Determine the grade from a score
"""
gradeA = "A"
gradeB = "B"
gradeC = "C"
gradeD = "D"
gradeF = "F"
score = float(input("Please write the score you got on the test, 0-10: "))
if score >= 9:
print("You did really good, your grade is:", gradeA, ". Congratulations")
elif score >= 7:
print("Your results are good. They earn you a:", gradeB, ". Better luck next time")
elif score >= 5:
print("Not too bad. You got a:", gradeC)
elif score >= 4:
print("That was close...:", gradeD)
elif score < 4:
print("You need to step up and take the test again:", gradeF)
else:
print("Grow up and write your score between 0 and 10")
Is there a way to get rid of the float and print the last statement if you write something else that the score from 0-10?
Something like this:
score = None
while score is None:
try:
score = float(input("Please write the score you got on the test, 0-10: "))
except ValueError:
continue
Keep on asking until the float cast works without raising the ValueError exception.
You could do
try:
score = float(input("Please write the score you got on the test, 0-10: "))
except ValueError:
print("Grow up and write your score between 0 and 10")
scoreGrade()
I would suggest to use EAFP approach and separate handling good and bad inputs.
score_as_string = input("Please write the score you got on the test, 0-10: ")
try:
score_as_number = float(score_as_string)
except ValueError:
# handle error
else:
print_grade(score_as_number)
def print_grade(score):
"""
Determine the grade from a score
"""
gradeA = "A"
gradeB = "B"
gradeC = "C"
gradeD = "D"
gradeF = "F"
if score >= 9:
print("You did really good, your grade is:", gradeA, ". Congratulations")
elif score >= 7:
print("Your results are good. They earn you a:", gradeB, ". Better luck next time")
elif score >= 5:
print("Not too bad. You got a:", gradeC)
elif score >= 4:
print("That was close...:", gradeD)
elif score < 4:
print("You need to step up and take the test again:", gradeF)
else:
print("Grow up and write your score between 0 and 10")
Note that typically you want to return from functions, not print inside them. Using function output as part of print statement is detail, and function does not have to know that.