1

据我了解,我可以使用 Python 中的abc模块来创建无法实例化的抽象类(以及其他不错的属性)。我尝试使用它来创建Exception类层次结构来表示我的应用程序的各种退出代码,但我仍然能够实例化我的基类,即使我不希望这种情况发生。这是一些演示问题的代码:

#!/usr/bin/env python3

import abc

class ExitCodeException(Exception):
    __metaclass__ = abc.ABCMeta

    def __init__(self, message):
        super().__init__()
        self._message = message

    @abc.abstractmethod
    def getExitCode(self):
        """Return the exit code for this exception"""
        return

class FatalException(ExitCodeException):
    def getExitCode(self):
        return 1

raise ExitCodeException("Oh no!")

我期待我的程序退出并出现ExitCodeException无法实例化的异常,但我只是得到了我期望的标准堆栈跟踪,如果ExitCodeException不是抽象的:

Traceback (most recent call last)
  File "./email2pdf_classexception", line 21, in <module>
    raise ExitCodeException("Oh no!")
__main__.ExitCodeException

我怎样才能解决这个问题?

4

1 回答 1

3

正如上面@BartoszKP 和@Debanshu Kundu 的评论中所讨论的那样,具体的超类似乎Exception是导致问题的原因。因此,我想出了一个稍微不同的模式,它似乎可以工作(据我所知,这是 Python 2 中的一种旧式模式,但似乎仍然有效):

#!/usr/bin/env python3

class ExitCodeException(Exception):
    def __new__(cls, *args, **kwargs):
        if cls is ExitCodeException:
            raise NotImplementedError("Base class may not be instantiated")
        return Exception.__new__(cls, *args, **kwargs)

    def __init__(self, message):
        super().__init__()
        self._message = message

    def getExitCode(self):
        """Return the exit code for this exception"""
        return

class FatalException(ExitCodeException):
    def getExitCode(self):
        return 1

raise FatalException("Oh no!")

这按预期工作;如果我将代码更改为直接实例化ExitCodeException,则会失败。

于 2014-10-18T19:28:40.183 回答