可以在Python中声明一个抽象异常吗?

时间:2013-11-20 21:36:31

标签: python oop python-2.7

我想在Python中声明用户定义的异常的层次结构。但是,我希望我的顶级用户定义类(TransactionException)是抽象的。也就是说,我打算TransactionException指定其子类需要定义的方法。但是,TransactionException永远不应该被实例化或提升。

我有以下代码:

from abc import ABCMeta, abstractmethod

class TransactionException(Exception):
    __metaclass__ = ABCMeta

    @abstractmethod
    def displayErrorMessage(self):
        pass

但是,上面的代码允许我实例化TransactionException ...

a = TransactionException()

在这种情况下,a没有意义,应该绘制一个例外。以下代码删除了TransactionExceptionException ...

的子类的事实
from abc import ABCMeta, abstractmethod

class TransactionException():
    __metaclass__ = ABCMeta

    @abstractmethod
    def displayErrorMessage(self):
        pass

此代码正确禁止实例化,但现在我无法引发TransactionException的子类,因为它不再是Exception

可以在Python中定义抽象异常吗?如果是这样,怎么样?如果没有,为什么不呢?

注意:我使用的是Python 2.7,但很乐意接受Python 2.x或Python 3.x的答案。

3 个答案:

答案 0 :(得分:3)

class TransactionException(Exception):

    def __init__(self, *args, **kwargs):
        raise NotImplementedError('you should not be raising this')


class EverythingLostException(TransactionException):

    def __init__(self, msg):
        super(TransactionException, self).__init__(msg)


try:
    raise EverythingLostException('we are doomed!')
except TransactionException:
    print 'check'

try:
    raise TransactionException('we are doomed!')
except TransactionException:
    print 'oops'

答案 1 :(得分:3)

Alex Martelli here对这个主题有一个很好的答案。从本质上讲,它描述了各种基类(__init__object和我假设list)的对象初始值设定项(Exception)在抽象方法中的表现在场。

当抽象类继承自object时(默认情况下,如果没有给出其他基类),它的__init__方法设置为object的方法,在检查所有抽象方法是否已实施时执行繁重的工作。

如果抽象类继承自不同的基类,它将获得该类“__init__方法”。其他类,例如listException,似乎不检查抽象方法实现,这就是允许实例化它们的原因。

另一个答案为此提供了建议的解决方法。当然,你拥有的另一个选择就是接受抽象类是可实例化的,并试图阻止它。

答案 2 :(得分:0)

我对抽象异常类的实现


class TransactionException(Exception):

    def __init__(self):
        self._check_abstract_initialization(self)

    @staticmethod
    def _check_abstract_initialization(self):
        if type(self) == TransactionException:
            raise NotImplementedError("TransactionException should not be instantiated directly")


class AnotherException(TransactionException):
    pass


TransactionException() # NotImplementedError: TransactionException should not be instantiated directly

AnotherException # passes