1

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"
EbraHim
  • 2,279
  • 2
  • 16
  • 28
  • Rule #1 of coding, NEVER copy and paste. Whenever you copy and paste that's really a function. – Kurt May 03 '16 at 05:24
  • I'm afraid I don't follow, what are you referring to? – Zachary McCauley May 03 '16 at 05:26
  • You might want to carefully review the course materials regarding this assignment. It probably discusses topics like functions, return values, and lists. – TigerhawkT3 May 03 '16 at 05:28
  • 2
    You have 5 identical code blocks with the only difference being the variable gradeX. Did you copy and paste that code and then change the variable name? I suspect you did. Instead of doing that, make a function. Granted that is sort of your question but nobody here is interested in doing your homework for you. – Kurt May 03 '16 at 05:29
  • @kurt that is certainly not the intent of this post. Being only weeks into my first ever coding class, there are concepts that are elusive to me and that I feel I cannot devise from the book and simply am looking for help. – Zachary McCauley May 03 '16 at 05:36
  • You need to actually put the while loop inside a function and call it whenever a grade is entered. It is apparent that the while loop is redundant. – Mukund Gandlur May 03 '16 at 05:36

2 Answers2

1

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.

Community
  • 1
  • 1
timgeb
  • 76,762
  • 20
  • 123
  • 145
  • Thank you for taking the time to write this all out. Going to re-do the entire thing while using your advice and trying to use functions more appropriately. – Zachary McCauley May 03 '16 at 05:45
  • Don't forget that the average of all numbers in a list is `average = sum(my_list) / len(my_list)`, you don't have to hard-code the length either. – Byte Commander May 03 '16 at 05:46
  • @ByteCommander Indeed, `calcaverage` should take two arguments (if you want a function for that at all). I missed that. – timgeb May 03 '16 at 05:50
0

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
>>>
EbraHim
  • 2,279
  • 2
  • 16
  • 28
  • Thank you for taking the time to write. I believe you used a number of things I have yet to learn (I am very new). But I intend to take this and make a tertiary page of the same code using your methods to learn something. – Zachary McCauley May 03 '16 at 05:47
  • @ZacharyMcCauley You are welcome. Google for `for loop in Python`, `dictionary in Python` and `formatted print in Python`. That's all you need for this program. Wish you success. – EbraHim May 03 '16 at 05:50
  • The `float` conversion inside `getAverage(...)` is superfluous. Also Python naming conventions are snake case (i.e. your function and variable names should look like `get_average` instead). Additionally, you can omit the `counter` variable because when you use it, its value is determined to be equal to `Test_num`. – Byte Commander May 03 '16 at 05:53
  • @ByteCommander Thank you dear friend. I updated my answer based on your tips. – EbraHim May 03 '16 at 05:57
  • You did not replace `counter` with `Test_num` : `get_average(sum_val, counter)` – Byte Commander May 03 '16 at 06:02