【问题标题】:What does "ABC" class do?“ABC”课是做什么的?
【发布时间】:2020-06-24 16:45:43
【问题描述】:

我写了一个继承另一个类的类:

class ValueSum(SubQuery):
    output = IntegerField()

pycharm 显示以下警告:

类 ValueSum 必须实现所有抽象方法

然后我alt+enterABC 添加到超类。我的警告消失了。我有几个问题:

  • 在编写子类时我应该总是这样做吗?

  • 手动实现所有方法有什么区别 与仅使用 ABC 相比?

  • ABC 是否在我的代码中添加了一些内容?

【问题讨论】:

  • SubQuery 是什么?
  • SubQuery 是一个 Django 模型表达式

标签: python python-3.x


【解决方案1】:

SubQuery 是一个抽象基类(根据abc module),具有一个或多个您未覆盖的抽象方法。通过将ABC 添加到基类列表中,您将ValueSum 本身定义为一个抽象基类。这意味着您不必强制重写这些方法,但这也意味着您不能实例化 ValueSum 本身。

PyCharm 提前警告你需要实现继承自SubQuery 的抽象方法;否则,当您实际尝试实例化 ValueSum 时,您会从 Python 收到错误消息。


至于从ABC 继承做了什么,答案是……不多。设置元类很方便。以下是等价的:

class Foo(metaclass=abc.ABCMeta):
    ...

class Foo(abc.ABC):
    ...

元类修改__new__,以便每次尝试创建类的实例时都会检查该类是否已实现父类中所有用@abstractmethod 修饰的方法。

【讨论】:

    【解决方案2】:

    这是遵循面向对象编程 (OOP) 的抽象类的要点。从抽象类继承的类需要实现所有抽象方法。如果它们本身是抽象的,则它们不需要。这些抽象方法就像接口的方法签名,内部没有任何实现。因此,您不能在不实现所有抽象方法的情况下创建非抽象类。 ABC 只是一个帮助类,通过派生它来创建新的抽象类。在这里你可以阅读更多关于 Python 抽象类的信息:https://docs.python.org/3/library/abc.html

    根据您的观察,您将ValueSum 标记为抽象。这意味着,ValueSum 的所有子类都需要实现ValueSum 及其所有抽象超类的抽象方法,包括SubQuery

    我编写从某个类抽象出来的类。

    没有。您编写了一个类,该类继承另一个。

    在编写子类时我应该总是这样做吗?

    没有。仅当您希望该类是抽象的时。

    手动实现所有方法与仅使用 ABC 有什么区别

    在这种情况下,您将实现转发到ValueSum 的所有子类。不使用ABC 将迫使您在ValueSum 内部实现抽象方法。

    ABC 是否在我的代码中添加了一些内容?

    没有。无论如何,不​​超过使用其他类/继承。

    【讨论】:

      【解决方案3】:

      “抽象基类”或abc.ABC 是一个辅助类

      https://docs.python.org/3/library/abc.html

      以下是它们存在的原因:

      集合模块有一些从 ABC 派生的具体类;当然,这些可以进一步推导出来。此外,collections.abc 子模块还有一些 ABC,可用于测试类或实例是否提供特定接口,例如是否可散列或是否为映射。

      这里有一个很好的例子:https://pymotw.com/2/abc/ | https://pymotw.com/3/abc/

      来自 pymotw:

      忘记正确设置元类意味着具体实现没有强制执行其 API。为了更容易正确设置抽象类,提供了一个自动设置元类的基类。

      abc_abc_base.py
      import abc
      
      
      class PluginBase(abc.ABC):
      
          @abc.abstractmethod
          def load(self, input):
              """Retrieve data from the input source
              and return an object.
              """
      
          @abc.abstractmethod
          def save(self, output, data):
              """Save the data object to the output."""
      
      
      class SubclassImplementation(PluginBase):
      
          def load(self, input):
              return input.read()
      
          def save(self, output, data):
              return output.write(data)
      
      
      if __name__ == '__main__':
          print('Subclass:', issubclass(SubclassImplementation,
                                        PluginBase))
          print('Instance:', isinstance(SubclassImplementation(),
                                        PluginBase))
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-11-18
        • 1970-01-01
        • 2011-08-31
        • 2013-12-24
        • 2023-04-10
        • 2020-08-30
        • 1970-01-01
        相关资源
        最近更新 更多