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"
6
  • Rule #1 of coding, NEVER copy and paste. Whenever you copy and paste that's really a function. Commented May 3, 2016 at 5:24
  • I'm afraid I don't follow, what are you referring to? Commented May 3, 2016 at 5:26
  • You might want to carefully review the course materials regarding this assignment. It probably discusses topics like functions, return values, and lists. Commented May 3, 2016 at 5: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. Commented May 3, 2016 at 5: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. Commented May 3, 2016 at 5:36

2 Answers 2

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.

Sign up to request clarification or add additional context in comments.

3 Comments

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.
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.
@ByteCommander Indeed, calcaverage should take two arguments (if you want a function for that at all). I missed that.
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
>>>

5 Comments

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.
@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.
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.
@ByteCommander Thank you dear friend. I updated my answer based on your tips.
You did not replace counter with Test_num : get_average(sum_val, counter)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.