patternpythonMinor
Getting a 4.0 GPA
Viewed 0 times
gpagettingstackoverflow
Problem
This is my code, for calculating a GPA for 7 subjects. It works, but is there a better way? Any hints on making it more flexible?
```
from __future__ import division
import string
print "This program will calculate a Semester GPA for a given set of courses. Enter 0 in all inputs, if you want to skip extra courses.\n"
cname1 = raw_input("First course name: ")
while True:
cred1 = raw_input("First course credit: ")
try:
i = int(cred1)
break
except ValueError:
print 'Invalid input, Should be an positive interger'
grade1 = raw_input("First course grade: ")
choice1 = grade1
while choice1 not in ["A+", "a+", "A", "a","A-", "a-", "B+", "b+", "B", "b", "B-", "b-", "C+", "c+", "C", "c","C-", "c-", "D+", "d+", "D", "d", "D-", "d-", "FAIL", "fail"]:
print 'Invalid choice'
grade1 = raw_input("First course grade: ")
users_turn = choice1 in ["A+", "a+", "A", "a","A-", "a-", "B+", "b+", "B", "b", "B-", "b-", "C+", "c+", "C", "c","C-", "c-", "D+", "d+", "D", "d", "D-", "d-", "FAIL", "fail"]
choice1 = grade1
cname2 = raw_input("Second course name: ")
while True:
cred2 = raw_input("Second course credit: ")
try:
i = int(cred2)
break
except ValueError:
print 'Invalid input, Should be an positive interger'
grade2 = raw_input("Second course grade: ")
choice2 = grade2
while choice2 not in ["A+", "a+", "A", "a","A-", "a-", "B+", "b+", "B", "b", "B-", "b-", "C+", "c+", "C", "c","C-", "c-", "D+", "d+", "D", "d", "D-", "d-", "FAIL", "fail"]:
print 'Invalid choice'
grade2 = raw_input("Second course grade: ")
users_turn = choice2 in ["A+", "a+", "A", "a","A-", "a-", "B+", "b+", "B", "b", "B-", "b-", "C+", "c+", "C", "c","C-", "c-", "D+", "d+", "D", "d", "D-", "d-", "FAIL", "fail"]
choice2 = grade2
cname3 = raw_input("Third course name: ")
while True:
cred3 = raw_input("Third course credit: ")
try:
i = int(cred3)
break
except ValueError:
```
from __future__ import division
import string
print "This program will calculate a Semester GPA for a given set of courses. Enter 0 in all inputs, if you want to skip extra courses.\n"
cname1 = raw_input("First course name: ")
while True:
cred1 = raw_input("First course credit: ")
try:
i = int(cred1)
break
except ValueError:
print 'Invalid input, Should be an positive interger'
grade1 = raw_input("First course grade: ")
choice1 = grade1
while choice1 not in ["A+", "a+", "A", "a","A-", "a-", "B+", "b+", "B", "b", "B-", "b-", "C+", "c+", "C", "c","C-", "c-", "D+", "d+", "D", "d", "D-", "d-", "FAIL", "fail"]:
print 'Invalid choice'
grade1 = raw_input("First course grade: ")
users_turn = choice1 in ["A+", "a+", "A", "a","A-", "a-", "B+", "b+", "B", "b", "B-", "b-", "C+", "c+", "C", "c","C-", "c-", "D+", "d+", "D", "d", "D-", "d-", "FAIL", "fail"]
choice1 = grade1
cname2 = raw_input("Second course name: ")
while True:
cred2 = raw_input("Second course credit: ")
try:
i = int(cred2)
break
except ValueError:
print 'Invalid input, Should be an positive interger'
grade2 = raw_input("Second course grade: ")
choice2 = grade2
while choice2 not in ["A+", "a+", "A", "a","A-", "a-", "B+", "b+", "B", "b", "B-", "b-", "C+", "c+", "C", "c","C-", "c-", "D+", "d+", "D", "d", "D-", "d-", "FAIL", "fail"]:
print 'Invalid choice'
grade2 = raw_input("Second course grade: ")
users_turn = choice2 in ["A+", "a+", "A", "a","A-", "a-", "B+", "b+", "B", "b", "B-", "b-", "C+", "c+", "C", "c","C-", "c-", "D+", "d+", "D", "d", "D-", "d-", "FAIL", "fail"]
choice2 = grade2
cname3 = raw_input("Third course name: ")
while True:
cred3 = raw_input("Third course credit: ")
try:
i = int(cred3)
break
except ValueError:
Solution
You've a long way to go here. Much of your code is repetitive, which (in case you have a mistake in your logic, for example) will give you maintenance headaches. Until your code is de-cluttered by refactoring (i.e. replacing it with simpler code having equivalent functionality - by analogy with refactoring algebraic expressions to make them simpler to understand) it's difficult to make other suggestions for improving it.
For example, you repeat the string
The blank lines in your code do not enhance readability.
You have many sections of logic which are essentially the same in all but details. You should really generalize these. For example, you write
This code essentially reads the credit and the grade for a specific conference, and could easily be encapsulated into a function such as
I have removed the
This allows you to simplify your login considerably by writing
Once you had made those changes you could consider building a list of inputs and then having the function return
At the end of this logic you will have a list of credits in
For example, you repeat the string
["A+", "a+", "A", "a","A-", "a-", "B+", "b+", "B", "b", "B-", "b-", "C+", "c+", "C", "c","C-", "c-", "D+", "d+", "D", "d", "D-", "d-", "FAIL", "fail"] umpteen times. If you assigned this to a global variable called valid_marks your code will read more lucidly, but more importantly if the set of valid marks were ever to change you could make the change in exactly one place rather than having to go through the code, possibly missing some occurrences.The blank lines in your code do not enhance readability.
You have many sections of logic which are essentially the same in all but details. You should really generalize these. For example, you write
cname4 = raw_input("Fourth course name: ")
while True:
cred4 = raw_input("Fourth course credit: ")
try:
i = int(cred4)
break
except ValueError:
print 'Invalid input, Should be an positive interger'
grade4 = raw_input("Fourth course grade: ")
choice4 = grade4
while choice4 not in ["A+", "a+", "A", "a","A-", "a-", "B+", "b+", "B", "b", "B-", "b-", "C+", "c+", "C", "c","C-", "c-", "D+", "d+", "D", "d", "D-", "d-", "FAIL", "fail"]:
print 'Invalid choice'
grade4 = raw_input("Fourth course grade: ")
users_turn = choice4 in ["A+", "a+", "A", "a","A-", "a-", "B+", "b+", "B", "b", "B-", "b-", "C+", "c+", "C", "c","C-", "c-", "D+", "d+", "D", "d", "D-", "d-", "FAIL", "fail"]
choice4 = grade4This code essentially reads the credit and the grade for a specific conference, and could easily be encapsulated into a function such as
def get_credit_and_score(course_name):
cname = raw_input(course_name+" name: ")
while True:
cred = raw_input(course_name" credit: ")
try:
i = int(cred)
break
except ValueError:
print 'Invalid input, Should be an positive integer'
grade = raw_input(course_name+" grade: ")
while grade not in valid_marks:
print 'Invalid choice'
grade = raw_input(course_name+" grade: ")
return cred, choiceI have removed the
choiceN and users_turn variables because I couldn't really see what use they served. This might have been an error, do feel free to correct me.This allows you to simplify your login considerably by writing
cred1, choice1 = get_credit_and_score("First course")
cred2, choice2 = get_credit_and_score("Second course")
...
cred7, choice7 = get_credit_and_score("Seventh course")Once you had made those changes you could consider building a list of inputs and then having the function return
None if the user indicated (by an empty entry for credit, for example) that they had completed their input. So then you could write something like:creds = []
choices = []
courses = ["First", "Second", "Third", "Fourth", "Fifth", "Sixth", "Seventh"]
for course in courses:
res = get_credit_and_score(course+" course")
if not res:
break
cred, choice = res
creds.append(cres)
choices.append(choice)At the end of this logic you will have a list of credits in
creds and a list of grades in choices and be in a position to calculate your required results more easily (I trust).Code Snippets
cname4 = raw_input("Fourth course name: ")
while True:
cred4 = raw_input("Fourth course credit: ")
try:
i = int(cred4)
break
except ValueError:
print 'Invalid input, Should be an positive interger'
grade4 = raw_input("Fourth course grade: ")
choice4 = grade4
while choice4 not in ["A+", "a+", "A", "a","A-", "a-", "B+", "b+", "B", "b", "B-", "b-", "C+", "c+", "C", "c","C-", "c-", "D+", "d+", "D", "d", "D-", "d-", "FAIL", "fail"]:
print 'Invalid choice'
grade4 = raw_input("Fourth course grade: ")
users_turn = choice4 in ["A+", "a+", "A", "a","A-", "a-", "B+", "b+", "B", "b", "B-", "b-", "C+", "c+", "C", "c","C-", "c-", "D+", "d+", "D", "d", "D-", "d-", "FAIL", "fail"]
choice4 = grade4def get_credit_and_score(course_name):
cname = raw_input(course_name+" name: ")
while True:
cred = raw_input(course_name" credit: ")
try:
i = int(cred)
break
except ValueError:
print 'Invalid input, Should be an positive integer'
grade = raw_input(course_name+" grade: ")
while grade not in valid_marks:
print 'Invalid choice'
grade = raw_input(course_name+" grade: ")
return cred, choicecred1, choice1 = get_credit_and_score("First course")
cred2, choice2 = get_credit_and_score("Second course")
...
cred7, choice7 = get_credit_and_score("Seventh course")creds = []
choices = []
courses = ["First", "Second", "Third", "Fourth", "Fifth", "Sixth", "Seventh"]
for course in courses:
res = get_credit_and_score(course+" course")
if not res:
break
cred, choice = res
creds.append(cres)
choices.append(choice)Context
StackExchange Code Review Q#75799, answer score: 8
Revisions (0)
No revisions yet.