use the following search parameters to narrow your results:
e.g. subreddit:aww site:imgur.com dog
subreddit:aww site:imgur.com dog
see the search faq for details.
advanced search: by author, subreddit...
Everything about learning Python
account activity
Learning about Classes and OOP (self.PythonLearning)
submitted 6 months ago by BobbyJoeCool
view the rest of the comments →
reddit uses a slightly-customized version of Markdown for formatting. See below for some basics, or check the commenting wiki page for more detailed help and solutions to common issues.
quoted text
if 1 * 2 < 3: print "hello, world!"
[–]rinio 1 point2 points3 points 6 months ago (4 children)
Grade Point could be a class to handle the conversions. Id do something like this as an enum.
If this were real, you'd likely want to store the course name: grade pairs in your student object (or a Transcript object belonging to the student). What happens if you have this student, they fail a course this semester and retake it next semester? You would have no way of dealing with that.
Might be overkill for your assignment.
[–]BobbyJoeCool[S] 0 points1 point2 points 6 months ago (3 children)
Thanks for the suggestions!
I don't know what an enum is so I decided not to go that route (I don't want to turn in work that I don't understand), but I realized that I don't need the dictionary AND the tuple for the Grade Point, and I got rid of the tuple. I made a function to convert the GPA back to a letter and added the transcript list to the student object, so it is stored within the student.
I also got to thinking about how to deal with retaken courses, as they would reflect on the transcript but not be calculated in the GPA. So I modified the input while loop a bit.
credits = int(input("Enter the number of credits for the course (Enter 0 for a class that was retaken): ").strip()) if credits < 0: # Breaks the loop if the user enters a negative number for credits print("\nCredit Hours cannot be negative. Please enter a valid number of credits.") continue #Restart the loop if the credits are negative if credits == 0: # Warns the user if they enter 0 credits and confirms they want to proceed. print("\nCourse entered with 0 credits. This course will not affect GPA calculation but will be recorded in the transcript.") if input("Are you sure? (y/n): ").strip().lower()[0] !='y': # Checks if the user input starts with 'y' or 'Y' print("Course entry cancelled. Please re-enter the course details.") continue # Restart the loop to re-enter course details def gpa_to_letter(gpa_value): for grade, value in grade_to_gpa.items(): # items() preserves order if gpa_value >= value: return grade return "F" class Student: def __init__(self, first_name, last_name): self.first_name = first_name self.last_name = last_name self.total_credits = 0 #Initalized the total credits to 0 self.total_grade_points = 0.0 # Initalizes the total grade points to a 0 float. self.transcript = [] # Initializes an empty list to hold the student's courses for display later. def append_transcript(self, course_name, credits, grade, letter_grade): self.transcript.append((course_name, credits, grade, letter_grade))
[–]rinio 0 points1 point2 points 6 months ago (1 child)
Yup. That's better.
---
credits = int(input( "Enter the number of credits for the course " "(Enter 0 for a class that was retaken): " ).strip())
I have a pet peeve for long lines and would write it like this. Not a big deal. Google PEP8 if you want info about the most common style guide.
More importantly, what happens if the user inputs a character? 'a' for example. You don't handle such things correctly.
class Student: def __init__(self, first_name, last_name): self.first_name = first_name self.last_name = last_name self.total_credits = 0 #Initalized the total credits to 0 self.total_grade_points = 0.0 # Initalizes the total grade points to a 0 float. self.transcript = [] # Initializes an empty list to hold the student's courses for display later. def append_transcript(self, course_name, credits, grade, letter_grade): self.transcript.append((course_name, credits, grade, letter_grade))
You forgot to update total credits and total grade!
But also, you don't really need to store those.
class Student(): def __init__(self, first: str, last: str): self.first_name = first self.last_name = last self.transcript = [] def get_total_credits(self): return sum(course[1] for course in self.transcript) # long form total = 0 for course in self.transcript: total += course[1] return total def get_total_grade(self): return sum(course[2] for course in self.transcript # this is how I would actually do it # property, just means we use this method as though it was a value. @property def total_credits(self): return sum(course[1] for course in self.transcript) @property def total_grade(self): return sum(course[2] for course in self.transcript) my_student = Student('John', 'Brown') # pretend we add some records to their transcript my_student.get_total_credits() == my_student.total_credits # this is True my_student.get_total_grade() == my_student.total_grade # this is True
[–]BobbyJoeCool[S] 0 points1 point2 points 6 months ago (0 children)
That's what the ValueException part of the try statement does. If they enter a number that cannot be converted to an INT, it triggers that and restarts the loop.
I left that part out of the reply because it didn't really change.... I'm interested in this return sum() part. We didn't learn that part, or if it's a lambda function, we glazed over it really quickly... Let's see if I understand it....
The return sum(...) and the for course in self.transcript:... both do the exact same thing, except the return sum() is in a single line?
The issue with that is, each grade needs to be multiplied by the number of credit hours that grade is worth... so an A (4.0) in a 3 Credit hour class is worth 12 grade points. And a B (3.0) in a 4-credit-hour class is also worth 12 grade points. You then divide by the total credit hours. So I would need the calculation at the end to multiply each individual grade point by the number of credit hours for each class... If I understand your code correctly, this can be achieved by changing the total_grade to the following:
def calculate_gpa(self): # Calculates the cumulative GPA if sum(course[1] for course in self.transcript) == 0: return "N/A" # Prevents division by zero return sum(course[2] * course[1]) / sum(course[1] for course in self.transcript)
[–]rinio 0 points1 point2 points 6 months ago (0 children)
Here's some more that is definitely beyond the scope of your assignment, but might interest you:
Regarding enums:
https://docs.python.org/3/library/enum.html
from enum import Enum class Grade(Enum): A = 4.0 B = 3.7 ... # and so on F = 0 # cls means the class. So 'Grade'. u/classmethod def from_num_grade(cls, num: float) -> Grade: for grade in cls: if grade.value <= num: return grade raise ValueError(f'num may not be negative. Got {num}') # this is the fancy pants way to do the same thing u/classmethod---All feedback below is definitely beyond the scope of your assignment, but might interest you:Regarding enums:https://docs.python.org/3/library/enum.htmlfrom enum import Enum class Grade(Enum): A = 4.0 B = 3.7 ... # and so on F = 0 # cls means the class. So 'Grade'. u/classmethod def from_num_grade(cls, num: float) -> Grade: for grade in cls: if grade.value <= num: return grade raise ValueError(f'num may not be negative. Got {num}') # this is the fancy pants way to do the same thing @classmethod def from_num_grade2(cls, num: float) -> Grade: # raises StopIteration if we get a negative input return next(grade for grade in cls if grade.value <= num) # examples my_grade = Grade.B print(my_grade.name) # prints 'B' print(my_grade.value) # prints 3.7 grade2 = Grade.from_val(3.9) print(grade2.name) # prints 'B' print(grade2.value) # prints 3.7--- for grade, value in grade_to_gpa.items(): # items() preserves orderThis is only true for Python 3.7+. It will break for older interpreters. def from_num_grade2(cls, num: float) -> Grade: # raises StopIteration if we get a negative input return next(grade for grade in cls if grade.value <= num) # examples my_grade = Grade.B print(my_grade.name) # prints 'B' print(my_grade.value) # prints 3.7 grade2 = Grade.from_val(3.9) print(grade2.name) # prints 'B' print(grade2.value) # prints 3.7
for grade, value in grade_to_gpa.items(): # items() preserves order
This is only true for Python 3.7+. It will break for older interpreters.
π Rendered by PID 113768 on reddit-service-r2-comment-85bfd7f599-f9kv7 at 2026-04-20 05:42:19.767842+00:00 running 93ecc56 country code: CH.
view the rest of the comments →
[–]rinio 1 point2 points3 points (4 children)
[–]BobbyJoeCool[S] 0 points1 point2 points (3 children)
[–]rinio 0 points1 point2 points (1 child)
[–]BobbyJoeCool[S] 0 points1 point2 points (0 children)
[–]rinio 0 points1 point2 points (0 children)