Skip to content

Intermediate · Projects: put it all together · topic 32 of 50 · 30 min

Project: marks and grade calculator

Explanation

You will build a report card calculator for a class: total marks, percentage, grade, pass or fail, the class topper and the class average. The project is split into small functions, and each one is tested before the next one is written. This is how real programmers build bigger programs.

Plan before you code

A project is just a bigger problem. The trick is to plan first. Write down three things: the inputs (what data comes in), the outputs (what answers must come out) and the steps in between. Each step usually becomes one small function.

Think of it like this: A tailor measures you, writes the numbers down and marks the cloth with chalk before cutting it. Cutting first and measuring later wastes cloth. Planning a program is the chalk mark: it costs a few minutes and saves hours of fixing.
PartFor our report card
InputsEach student: a name and marks in 5 subjects, each out of 100
OutputsTotal, percentage, grade, PASS or FAIL, class topper, class average
Stepscheck marks, add them, find percentage, find grade, check pass, repeat for the class

Our grading scheme

Every school board publishes its own rules. For this project we use one simple scheme and write it down clearly, so the program and the people agree.

PercentageGrade
90 and aboveA
75 to below 90B
60 to below 75C
33 to below 60D
below 33F
Careful: Pass rule: a student passes only if EVERY subject is 33 or more. A student with 95 in four subjects and 20 in one subject fails, even though the percentage is high. In that case our report card shows grade F.

Step 1: check, total and percentage

We keep one student's marks in a dictionary: subject name to mark. The first function checks that every mark is between 0 and 100, because a typing mistake like 870 would spoil every answer after it.

python
def check_marks(marks):
    for subject, mark in marks.items():
        if not 0 <= mark <= 100:
            raise ValueError(f"{subject}: mark {mark} must be between 0 and 100")

def total(marks):
    check_marks(marks)
    return sum(marks.values())

def percentage(marks):
    max_total = len(marks) * 100
    return round(total(marks) / max_total * 100, 2)

marks = {"English": 78, "Hindi": 85, "Maths": 92, "Science": 88, "Social Science": 81}
print(total(marks))       # 424
print(percentage(marks))  # 84.8
Each function does one job. percentage() reuses total(), which reuses check_marks().

Step 2: grade and pass

python
def grade(percent):
    if percent >= 90:
        return "A"
    elif percent >= 75:
        return "B"
    elif percent >= 60:
        return "C"
    elif percent >= 33:
        return "D"
    return "F"

def has_passed(marks):
    return all(mark >= 33 for mark in marks.values())

print(grade(84.8))                                 # B
print(has_passed({"Maths": 95, "Hindi": 20}))      # False
The if/elif chain checks from the highest band down, so the first match is the right grade.

Step 3: the whole class

Now we join the pieces. report() builds one student's result as a dictionary. class_topper() uses max() with a key, and class_average() uses statistics.mean(). Here is the complete program in one place.

python
import statistics

def total(marks):
    return sum(marks.values())

def percentage(marks):
    return round(total(marks) / (len(marks) * 100) * 100, 2)

def grade(percent):
    for limit, letter in [(90, "A"), (75, "B"), (60, "C"), (33, "D")]:
        if percent >= limit:
            return letter
    return "F"

def has_passed(marks):
    return all(mark >= 33 for mark in marks.values())

def report(student):
    marks = student["marks"]
    passed = has_passed(marks)
    pct = percentage(marks)
    return {
        "name": student["name"],
        "total": total(marks),
        "percentage": pct,
        "grade": grade(pct) if passed else "F",
        "result": "PASS" if passed else "FAIL",
    }

def class_topper(students):
    best = max(students, key=lambda s: total(s["marks"]))
    return best["name"]

def class_average(students):
    return round(statistics.mean(percentage(s["marks"]) for s in students), 2)

students = [
    {"name": "Aarav", "marks": {"Eng": 78, "Hin": 85, "Mat": 92, "Sci": 88, "SSt": 81}},
    {"name": "Diya", "marks": {"Eng": 91, "Hin": 89, "Mat": 97, "Sci": 94, "SSt": 90}},
    {"name": "Kabir", "marks": {"Eng": 65, "Hin": 30, "Mat": 72, "Sci": 58, "SSt": 61}},
]
for s in students:
    print(report(s))
print("Topper:", class_topper(students))
print("Class average:", class_average(students))
Kabir has a good total but 30 in Hindi, so his result is FAIL with grade F.

Step 4: test with answers you already know

Testing means running your functions on inputs where you already know the right answer. Work a few out by hand, then let assert compare. Pay extra attention to the edges: exactly 33, exactly 90, and just below them. Bugs love edges.

python
def grade(percent):
    for limit, letter in [(90, "A"), (75, "B"), (60, "C"), (33, "D")]:
        if percent >= limit:
            return letter
    return "F"

assert grade(90) == "A", "exactly 90 is an A"
assert grade(89.99) == "B", "just below 90 is a B"
assert grade(33) == "D", "exactly 33 passes with D"
assert grade(32.99) == "F", "below 33 is F"
print("All grade tests passed")
If any assert is wrong, Python stops and shows its message.
Tip: Build one function, test it, then build the next. If you write all six functions first and then run them, you will not know which one has the bug.

Watch the lesson

Project: marks and grade calculator · 1/7

Project: marks and grades

Welcome to your first project. You will build a report card calculator for a whole class, one small function at a time.

Prefer a video by a teacher? Find free videos on “python student marks grade calculator project” on YouTube ↗

In real life: A class teacher at result time

Every March a class teacher in a government school types the marks of 40 students into a spreadsheet and works out totals, percentages and grades by hand. The same few functions do it in under a second, never make an addition mistake, and can be reused next year with a new list of students.

python
marks = {"English": 70, "Hindi": 64, "Maths": 88, "Science": 75, "Social Science": 69}
total = sum(marks.values())
percent = total / (len(marks) * 100) * 100
passed = all(m >= 33 for m in marks.values())
print(total, round(percent, 2), "PASS" if passed else "FAIL")
The core of a report card in five lines.

Practice (0/3 done)

Task 1 · Code · Python

Write percentage(marks) where marks is a dictionary of subject to mark (each out of 100). Return the percentage rounded to 2 decimal places. Example: {"Maths": 90, "Science": 75} gives 82.5.

Task 2 · Code · Python

Write grade(percent) using this scheme: 90 and above "A", 75 and above "B", 60 and above "C", 33 and above "D", otherwise "F".

Task 3 · Code · Python

Write class_topper(students). Each student is a dictionary like {"name": "Diya", "marks": {"Maths": 97, "Science": 94}}. Return the NAME of the student with the highest total. If two students tie, return the one who comes first in the list.

Quick quiz

Question 1

1.What should you write down BEFORE coding a project?

Question 2

2.With our scheme, what grade is exactly 75 percent?

Question 3

3.Marks are {"Maths": 95, "Science": 96, "Hindi": 25}. What is the result?

Question 4

4.Which line checks that every mark is at least 33?

Question 5

5.Why test grade(90) and grade(89.99) separately?

Read more (free)

Pass the quiz (60% or more) or mark this topic as done when you are ready.

Your progress is saved on this device only.

← Previous: CSV files and simple statistics