Собственный класс исключений не проходит неизвестные тесты

Мне для выполнения задания нужно написать программу со следующими условиями:

  1. Собственный класс исключений

Напишите класс исключения ParseError, который будет являться наследником класса Exception.

  1. Снабдите созданный класс документ-строкой: """ Error while parsing file """.

  2. Конструктор класса ParseError должен принимать необязательные именованные аргументы line_no (номер строки) и text (текст, который вызвал ошибку).

  3. Опишите метод __str__, создающий сообщение об ошибке по следующей логике:

  • если не переданы ни номер строки, ни текст, вызывается стандартный метод Exception;

  • если передан только номер строки, метод выдает "cannot parse text on line ...";

  • если передан только текст, метод выдает "cannot parse text: '...'" (текст должен выглядеть так, как его выдает функция repr);

  • если переданы и номер строки, и текст, метод выдает: "cannot parse text on line ...: '...'".

Пример работы программы:

>>> raise ParseError('some standard message')
Traceback (most recent call last):
...
__main__.ParseError: some standard message

>>> raise ParseError(line_no=10)
Traceback (most recent call last):
...
__main__.ParseError: cannot parse text on line 10

>>> raise ParseError(text='abc')
Traceback (most recent call last):
__main__.ParseError: cannot parse text: 'abc'

>>> raise ParseError(line_no=10, text='...')
Traceback (most recent call last):
...
__main__.ParseError: cannot parse text on line 10: '...'

Пояснение: любой класс исключения принимает произвольное число аргументов (в сигнатуре функции это выглядит как *args). Класс-наследник должен поддерживать весь интерфейс родителя, поэтому в вашем классе также должны быть *args, которые нужно передать выше по иерархии наследования с помощью функции super.

Любые аргументы, указанные после аргумента со «звездочкой», можно передать только по имени, поэтому они называются именованными. Чтобы сделать их необязательными, нужно дать им значение по умолчанию.

Я написал следующую программу, но она не проходит тесты, которые неизвестны:

class ParseError(Exception):
    """ Error while parsing file """

    def __init__(self, line_no=None, text=None):
        self.line_no = line_no
        self.text = text

    def __str__(self):
        if self.line_no == None and self.text == None:
            return f"some standard message"
        elif self.text == None:
            return f"cannot parse text on line {self.line_no}"
        elif self.line_no == None:
            return "cannot parse text: " + repr(self.text)
        else:
            return f"cannot parse text on line {self.line_no}: " + repr(self.text)

Подскажите, что я делаю неправильно?


Ответы (2 шт):

Автор решения: Vladimir Bogdanov

Мне кажется метод __str__ не нужно переопределять. Пусть срабатывает стандартный из Exception. Достаточно на основании двух именованных параметров задавать текст, который должен вывести Exception. Для этого в наследнике в методе __init__ смотрим на два этих параметра и формируем нужное сообщение об ошибке, либо ничего не делаем и инициализируем Exception со стандартным *args. Т.к. по условию задания не требуется дальнейшая обработка именованных параметров, то и хранить их в атрибутах экземпляра не нужно. Т.к. args - это кортеж, то для унификации сгенерированное сообщение об ошибке оборачиваем в кортеж.

class ParseError(Exception):
    """ Error while parsing file """

    def __init__(self, *args, line_no=None, text=None):
        match (line_no is None, text is None):
            case (False, True):
                args = (f"cannot parse text on line {line_no}",)
            case (True, False):
                args = (f"cannot parse text on line {text!r}",)
            case (False, False):
                args = (f"cannot parse text on line {line_no}: {text!r}",)

        super().__init__(*args)
→ Ссылка
Автор решения: Charlz_Klug

Вот такой код благополучно проходит проверки:

class ParseError(Exception):
""" Error while parsing file """

def __init__(self, *args, line_no=None, text=None):
    super().__init__(*args)
    match (line_no is None, text is None):
        case (True, True):
            self.text = super().__str__()
        case (True, False):
            self.text = f'cannot parse text: \'{text}\''
        case (False, True):
            self.text = f'cannot parse text on line {line_no}'
        case (False, False):
            self.text = f'cannot parse text on line {line_no}: \'{text}\''

def __str__(self):
    return self.text
→ Ссылка