Creating exceptions that are co-operative

2019-07-31 17:07发布

问题:

The Python docs state:

Programs may name their own exceptions by creating a new exception class (see Classes for more about Python classes). Exceptions should typically be derivedfrom the Exception class, either directly or indirectly.

...

When creating a module that can raise several distinct errors, a common practice is to create a base class for exceptions defined by that module, and subclass that to create specific exception classes for different error conditions.

From Python’s super() considered super!:

Each level strips-off the keyword arguments that it needs so that the final empty dict can be sent to a method that expects no arguments at all (for example, object.init expects zero arguments)

Suppose I have the following StudentValueError and MissingStudentValue exceptions.

class StudentValueError(Exception):
    """Base class exceptions for Student Values"""
    def __init__(self, message, **kwargs):
        super().__init__(**kwargs)
        self.message = message # You must provide at least an error message.


class MissingStudentValue(StudentValueError):
    def __init__(self, expression, message, **kwargs):
        super().__init__(message, **kwargs)
        self.expression = expression

    def __str__(self):
        return "Message: {0} Parameters: {1}".format(self.message, self.expression)

I want to create exceptions that are co-operative. I have two questions:

  1. In that case, the Exception class constructor expects zero arguments (empty dict), correct?
  2. Does my example violate LSP?

The accepted answer provided here inherits from ValueError.

回答1:

Exception takes no keyword arguments, it takes only variable amount of positional parameters via *args, so you need to change **kwargs to *args. Also I would recommend to pass message and expression together with *args to super() call. After all, the example, which probably doesn't violate LSP:

class StudentValueError(Exception):
    """Base class exceptions for Student Values"""
    def __init__(self, message='', *args):
        super().__init__(message, *args)
        self.message = message 


class MissingStudentValue(StudentValueError):
    def __init__(self, message='', expression='', *args):
        super().__init__(message, expression, *args)
        self.expression = expression

    def __str__(self):
        return "Message: {0} Parameters: {1}".format(self.message, self.expression)


e = Exception('message', 'expression', 'yet_another_argument')
print(e)
e = StudentValueError('message', 'expression', 'yet_another_argument')
print(e)
e = MissingStudentValue('message', 'expression', 'yet_another_argument')
print(e)
e = MissingStudentValue()
print(e)