pythonclassabstract-class

Implementing abstract classes


I am a begginer in Python coding and I try to learn abstract classes. I have a problem with implementing two exams which extend abstract class Exam, defining contract for diagnostic test.

class Person:
def __init__(self, name: str, age: int):
self.name = name
self.age = age

class Patient(Person):
def __init__(self, name: str, age: int, id: str, symptoms: list\[str\], cholesterol: float, iron_level: float):
super().__init__(name, age)
self.id = id
self.symptoms = symptoms
self.cholesterol = cholesterol
self.iron_level = iron_level\`

class CholesterolExam(Exam):
def __init__(self):
super().__init__('Cholesterol Exam')

    def perform_exam(self,cholesterol_exam):
        if cholesterol_exam >= 200:
            return False
        return True

class IronLevelExam(Exam):
def __init__(self):
super().__init__('Iron Exam')

    def perform_exam(self,iron_level_exam):
        if iron_level_exam>50 and iron_level_exam<170:
            return True    

class Test03(unittest.TestCase):
    def test_doctor(self):
        cholesterol_exam = CholesterolExam()
        iron_level_exam = IronLevelExam()
        p = Patient('John', 30, '001', ['cough', 'fever'], 180, 300)
        cholesterol_exam_result, iron_exam_result = [exam.perform_exam(p) for exam in [cholesterol_exam, iron_level_exam]]

        self.assertTrue(cholesterol_exam_result)
        self.assertFalse(iron_exam_result)

test(Test03)

I get the error message:

line 32, in test_doctor cholesterol_exam_result, iron_exam_result = [exam.perform_exam(p) for exam in [cholesterol_exam, iron_level_exam]]

line 12, in perform_exam if cholesterol_exam >= 200:

TypeError: '>=' not supported between instances of 'Patient' and 'int'


Solution

  • You are comparing a Patient object with 200, which is an Integer, but the actual thing you should have compared the number with was, probably, a field from p.

    You have two options:

    1. Either call exam.perform_exam with another parameter that resembles an int, such as p.cholesterol
    2. Assuming that exam.perform_exam needs a Patient, compare an integer field from the parameter against that 200.

    This is not about the abstract class, but about Python's lack of type inference.

    An example for the first case mentioned above:

    cholesterol_exam_result, iron_exam_result = [exam.perform_exam(p.cholesterol) for exam in [cholesterol_exam, iron_level_exam]]