Mark sheet to ranks and grades with Python
Teachers and class representatives do this every exam: add up five subjects, work out the percentage and grade, rank the class and find the topper in each subject.
This program does all of it for a class in one go. Change the pass mark below and press Run to see who would need a re-test.
CBSE-style totals, grades, ranks and subject toppers for a whole class.
The Python behind it · 29 lines
1pass_mark = 40 # out of 100, per subject23# Class 12 marks: Maths, Physics, Chemistry, English, CS4students = {5 "Aarav": [92, 88, 79, 85, 98], "Diya": [78, 91, 88, 93, 95],6 "Kabir": [65, 58, 72, 80, 88], "Meera": [99, 94, 96, 90, 97],7 "Rohan": [45, 52, 38, 70, 66], "Sana": [84, 79, 91, 88, 90],8 "Vihaan": [71, 66, 69, 75, 82], "Ishita": [88, 95, 90, 84, 93],9}1011def grade(pct):12 for cutoff, g in [(91, "A1"), (81, "A2"), (71, "B1"), (61, "B2"), (51, "C1"), (41, "C2")]:13 if pct >= cutoff:14 return g15 return "D"1617ranked = sorted(students.items(), key=lambda kv: -sum(kv[1]))18print(f"{'Rank':<5}{'Name':<8}{'Total':>6}{'%':>7} Grade Result")19for rank, (name, marks) in enumerate(ranked, start=1):20 pct = sum(marks) / 521 failed = [m for m in marks if m < pass_mark]22 result = "PASS" if not failed else f"Re-test ({len(failed)})"23 print(f"{rank:<5}{name:<8}{sum(marks):>6}{pct:>7.1f} {grade(pct):<5} {result}")2425subjects = ["Maths", "Physics", "Chemistry", "English", "CS"]26print("\nSubject toppers:")27for i, subject in enumerate(subjects):28 top = max(students, key=lambda n: students[n][i])29 print(f" {subject:<10} {top} ({students[top][i]})")
How the code works, step by step
1.Keep marks in a dictionary
Each student's name maps to a list of five marks in a fixed subject order. A dictionary of lists is a natural shape for a mark sheet.
3# Class 12 marks: Maths, Physics, Chemistry, English, CS4students = {5 "Aarav": [92, 88, 79, 85, 98], "Diya": [78, 91, 88, 93, 95],6 "Kabir": [65, 58, 72, 80, 88], "Meera": [99, 94, 96, 90, 97],7 "Rohan": [45, 52, 38, 70, 66], "Sana": [84, 79, 91, 88, 90],8 "Vihaan": [71, 66, 69, 75, 82], "Ishita": [88, 95, 90, 84, 93],9}2.Turn a percentage into a grade
grade() walks a list of (cutoff, grade) pairs from the top and returns the first one the percentage reaches. Changing the grading scheme means editing one list, not a chain of if statements.
11def grade(pct):12 for cutoff, g in [(91, "A1"), (81, "A2"), (71, "B1"), (61, "B2"), (51, "C1"), (41, "C2")]:13 if pct >= cutoff:14 return g15 return "D"3.Rank the class
sorted with key=lambda kv: -sum(kv[1]) orders students by total, highest first, and enumerate(start=1) numbers the ranks. A list comprehension finds every subject below the pass mark.
17ranked = sorted(students.items(), key=lambda kv: -sum(kv[1]))18print(f"{'Rank':<5}{'Name':<8}{'Total':>6}{'%':>7} Grade Result")19for rank, (name, marks) in enumerate(ranked, start=1):20 pct = sum(marks) / 521 failed = [m for m in marks if m < pass_mark]22 result = "PASS" if not failed else f"Re-test ({len(failed)})"23 print(f"{rank:<5}{name:<8}{sum(marks):>6}{pct:>7.1f} {grade(pct):<5} {result}")4.Find each subject's topper
max with a key function returns the student with the highest mark in subject i. It is the same max you know, just told what to compare.
25subjects = ["Maths", "Physics", "Chemistry", "English", "CS"]26print("\nSubject toppers:")27for i, subject in enumerate(subjects):28 top = max(students, key=lambda n: students[n][i])29 print(f" {subject:<10} {top} ({students[top][i]})")
Make it yours
- Read the marks from a CSV exported from Excel or Google Sheets.
- Give students with equal totals the same rank.
- Write each student's result to its own text file to print or share.
Questions
- Is this good for a CBSE Class 11 or 12 project?
- It uses the topics in the Class 11 and 12 Python syllabus (lists, dictionaries, functions, loops and sorting), so it makes a good starting point. Add file handling and your own data to make it your project.
- Are these the official CBSE grade cutoffs?
- They follow the familiar A1 to D pattern but are an example. Check your board's current scheme and change the list in grade() to match it.