【问题标题】:Making an abstract base class that inherits from Exception创建一个继承自 Exception 的抽象基类
【发布时间】:2019-12-30 16:50:04
【问题描述】:

我正在尝试为我的应用程序中引发的异常创建一个自定义基类。我想让它成为一个不能直接实例化的抽象类(使用 abc 模块),强迫自己为不同类型的错误情况定义更具体的具体子类。

我可以定义一个继承自自定义具体类的抽象类。然而,令我惊讶的是,如果我让抽象类(直接或间接)从 Exception 继承,它可以再次被直接实例化,从而破坏了首先使其抽象的目的。

我想了解这里发生了什么,以便我可以将我的自定义异常类抽象为真实而不是直接实例化。

我尝试了将自定义异常类声明为抽象的不同变体,包括使用metaclass=abc.ABCMeta 语法以及从abc.ABC 继承。不管它被声明为抽象的方式如何,只要我让它继承自Exception,它就不再像抽象类一样。

对我来说相关的 Python 版本是 3.5、3.6 和 3.7。我已经在 Python 3.5.2 (Ubuntu 16.04) 和 3.6.8 (Ubuntu 18.04) 上测试了以下代码。

以下似乎按预期工作:由于抽象方法 (TypeError: Can't instantiate abstract class AppException with abstract methods abs_method),实例化 AppException 失败。

请注意,虽然这些类被称为*Exception,但它们(还)不是从真正的内置 Exception 类继承的。

import abc

class BaseException():
    pass

class AppException(BaseException, abc.ABC):

    @abc.abstractmethod
    def abs_method(self):
        pass

class ConcreteException(AppException):

    def abs_method(self):
        return "concrete method"

# BaseException can be instantiated just fine
a = BaseException()

# ConcreteException can be instantiated just fine
c = ConcreteException()

# It shouldn't be possible to instantiate AppException directly,
# so this line should raise a TypeError
b = AppException()

当我将 BaseException 的定义更改为从实际的 Exception 类继承时:

class BaseException(Exception):
    pass

然后TypeError 消失了,所以这次 AppException 的实例化确实起作用了。 AppException 不再表现为抽象类,尽管在我的理解中应该如此。

这是actual code,目前作为 PR 草案一直停留在我弄清楚发生了什么之前。

【问题讨论】:

    标签: python python-3.x inheritance abstract-base-class


    【解决方案1】:

    这在SO discussion 前面已经介绍过。

    没有明显的解决方案,但一种可能的解决方法(来自上面的 SO 讨论)是将 __init__ 方法添加到“抽象”扩展类中,以防止它被直接实例化。

    【讨论】:

      猜你喜欢
      • 2019-12-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-15
      • 2018-06-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多