The 'answer' in the mark scheme is wrong. It is broken. It doesn't work. In other words, your code is correct. You should use your code, not the mark scheme. To me, it looks as if someone without actual Python programming experience wrote that up and didn't verify if it actually would run. I would not expect future exams to make such blatant errors, and if they did you would have plenty of ground to challenge the results.
For functions defined on a class, when you use the function name as an attribute on an instance and call it, Python will pass in the instance as the first positional argument to the function, automatically. We only use the name self for that argument by convention.
So for the SetFinalMark() method, for example, what will happen is that Python passes in the instance as the first argument, and so that's assigned to the name Mark. You can call it as Chomba.SetFinalMark(), at which point Mark is set to reference the instance you named Chomba. The method then will raise a different exception, because the ExamResult() class doesn't support comparisons so Mark >= 0 will raise a TypeError exception (TypeError: '>=' not supported between instances of 'ExaminationPaper' and 'int').
And that also means that the GetFinalMark() method will always fail, because it doesn't take any parameters (TypeError: GetFinalMark() takes 0 positional arguments but 1 was given).
There are other issues with the mark scheme code. Because there is no self parameter the implementation of SetGrade and SetFinalMark and GetFinalMark are instead treating Grade and FinalMark as global variables, and so will raise NameError exceptions if you didn't first run into all those TypeError exceptions. And in Python, the return statement is not a function. While return(<expression) works, it surely will confuse beginning programmers and not help when making a distinction between expressions and statements. The (..) parentheses are really part of the expression and would be redundant if there was a space after return; you should really use return <expression> without parentheses.
Finally, and this is an issue with the assignment, not just with the mark scheme, the whole example goes against the Python style guide naming conventions, which are there to help make it easy to spot classes versus other names. Ideally, only ExaminationPaper should use CamelCase naming, everything else should use snake_case (lower-cased words joined by underscores), including all attribute names, parameters, and method names.
I had a look around, and this looks like the UK May/June 2019 A-level Computer Science exam past paper (#4) (available at several sites, this is the mark scheme one one such site, to go with this past paper). If so, then it looks like the authors got their conventions mixed up. The paper allows for the student to choose between Python, Pascal and Visual Basic, and their code looks like the author applied Visual Basic principles to Python code. In Visual Basic, there is no self parameter. The choice to allow for multiple implementation languages then also limited how much room there is for applying the normal Python naming conventions.
But if Python conventions don't apply, then I also note that they are also using attribute names as __FinalMark in the marking scheme, showing a lack of understanding of how Python treats encapsulation. I'll not go into detail here, but I've written an answer before that explains why using double-underscore names is wrong here. That they then completely failed to use the correct attribute names makes their version of the 'correct' implementation for the three methods you were asked to write even more wrong.
If you wanted to implement everything 'correctly' according to the normal Python conventions and style guide (including using properties and a better name for how determining the grade based on 3 thresholds is handled), you'd end up with:
class ExaminationPaper:
def __init__(self, centre_number, candidate_number):
self.paper_id = f"{centre_number}{candidate_number}"
self.grade = "Fail"
self._final_mark = 0
def determine_grade(self, dist_mark, merit_mark, pass_mark):
if self._final_mark >= dist_mark:
self.grade = "Distinction"
elif self._final_mark >= merit_mark:
self.grade = "Merit"
elif self._final_mark >= pass_mark:
self.grade = "Pass"
else:
self.grade = "Fail"
@property
def final_mark(self):
return self._final_mark
@final_mark.setter
def final_mark(self, mark):
if not (0 <= mark <= 90):
raise ValueError(f"Final mark {mark} not in range 0-90")
self._final_mark = mark
chomba = ExaminationPaper(559, 9022)
try:
chomba.final_mark = 80
except ValueError as e:
print("Could not set the final mark:", e)
else:
chomba.determine_grade(80, 70, 55)
print(f"For {chomba.paper_id}, the student was given a {chomba.grade}")
I fully admit that that's well out of reach of an A-level paper, however. :-) And given the mark scheme, you wouldn't even get your marks unless the person marking the paper actually knew enough about Python programming to recognize why the above deviates from the scheme.