为什么需要在其元类派生自ABCMeta的类中使用@abstractmethod?

彼得罗·马尔凯西

PEP 3119指出:

所述@abstractmethod装饰应仅在类体中使用,并且仅用于一个其元类是(衍生自)ABCMeta不支持将动态方法添加到类,或在创建方法或类后尝试修改其抽象状态。

但是,我找不到为什么的解释。具体来说,仅@abstractmethod在未明确继承自的类中使用时,我没有注意到行为上的差异ABCMeta在下面的简单示例中,如果我理解正确,则正确的处理方式将是:

import six
from abc import ABCMeta
from abc import abstractmethod

class Base(six.with_metaclass(ABCMeta)):
    def __init__(self):
        print('Init abstract base')

    @abstractmethod
    def do_something(self):
        pass

class Subclass(Base):
    def __init__(self):
        super(Subclass, self).__init__()

    def do_something(self):
        print('Done.')

sub = Subclass()
sub.do_something()

但是,如果我让Baseobject仅从继承,并且仅在需要时使用装饰器,则我注意到行为没有变化。

from abc import abstractmethod

class Base(object):
    def __init__(self):
        print('Init abstract base')

    @abstractmethod
    def do_something(self):
        pass

class Subclass(Base):
    def __init__(self):
        super(Subclass, self).__init__()

    def do_something(self):
        print('Done.')

sub = Subclass()
sub.do_something()

我发现即使在更复杂的体系结构上也是如此,所以我想知道:后一种方法何时会失败?

布鲁诺·德斯胡里尔斯

您没有看到任何区别,因为您的第一个子类确实实现了do_somethingabstractmethod。

注释掉这do_something两个版本中子类的定义,您会发现在第一种情况下TypeError尝试实例化子类时会得到一个-您还将尝试实例化第一个版本Base类本身的FWIW。在第二个版本中,您可以实例化这两个类(因为它们是抽象的,所以不可能),然后调用abstractdo_something方法-破坏了ABC的要点之一。

您还将错过ABC FWIW的许多其他有趣功能...

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

为什么我们需要在 Spring Data JPA 中使用 @Transactional 注释 Service 类

来自分类Dev

为什么在python中使用抽象类时要声明metaclass=abc.ABCMeta?

来自分类Dev

为什么React类组件始终需要在其构造函数中调用super(props)?

来自分类Java

为什么要在Spring中使用self类?

来自分类Python

为什么要在Python中使用抽象基类?

来自分类Dev

为什么要在C ++中使用嵌套类?

来自分类Dev

为什么需要在类python(self.x = x)中使用带点的任何字符串带有self?

来自分类Dev

为什么派生类需要使用基类构造函数

来自分类Dev

为什么在JavaScript中使用TypeScript类需要`.default`?

来自分类Dev

为什么不能在带有模板的派生类中使用基类的别名?

来自分类Dev

元类:为什么方法不继承自基类?

来自分类Dev

为什么构造函数需要在类的后面精确命名?

来自分类Dev

为什么需要在构造函数中调用超类?

来自分类Dev

为什么需要在实体类上放置@NamedQuery?

来自分类Dev

需要在JS和PHP中使用相同的类,正确的处理方式是什么?

来自分类Dev

如果其基类派生自IEnumerable <T>,为什么不能在DataRowCollection上使用LINQ

来自分类Dev

为什么abc.ABCMeta抽象实例化检查不能用于`list`和`dict`的派生类?

来自分类Dev

为什么派生类的构造函数要在C ++中初始化虚拟基类?

来自分类Dev

为什么后台工作人员需要在其 DoWork 事件处理程序中使用 Thread.Sleep()?

来自分类Dev

为什么在C ++中使用基类指针无法到达派生类的成员函数?它的设计思想是什么?

来自分类Dev

是否需要在单例类中使用弱引用?

来自分类Dev

范围问题:将帐户凭据存储在promise中的新类对象中,但现在需要在其余类中使用此对象

来自分类Dev

如何在基类中使用派生类成员设计我需要的类?

来自分类Dev

为什么C ++不允许派生类在初始化列表中使用基类成员?

来自分类Dev

为什么在创建模型表单时需要“类元”?

来自分类Dev

为什么需要在nodejs中使用path模块?

来自分类Dev

为什么我需要在 shareReplay 中使用管道?

来自分类Dev

为什么我需要在Android中使用super()?

来自分类Dev

为什么我需要在 Django 中使用 SlugField?

Related 相关文章

  1. 1

    为什么我们需要在 Spring Data JPA 中使用 @Transactional 注释 Service 类

  2. 2

    为什么在python中使用抽象类时要声明metaclass=abc.ABCMeta?

  3. 3

    为什么React类组件始终需要在其构造函数中调用super(props)?

  4. 4

    为什么要在Spring中使用self类?

  5. 5

    为什么要在Python中使用抽象基类?

  6. 6

    为什么要在C ++中使用嵌套类?

  7. 7

    为什么需要在类python(self.x = x)中使用带点的任何字符串带有self?

  8. 8

    为什么派生类需要使用基类构造函数

  9. 9

    为什么在JavaScript中使用TypeScript类需要`.default`?

  10. 10

    为什么不能在带有模板的派生类中使用基类的别名?

  11. 11

    元类:为什么方法不继承自基类?

  12. 12

    为什么构造函数需要在类的后面精确命名?

  13. 13

    为什么需要在构造函数中调用超类?

  14. 14

    为什么需要在实体类上放置@NamedQuery?

  15. 15

    需要在JS和PHP中使用相同的类,正确的处理方式是什么?

  16. 16

    如果其基类派生自IEnumerable <T>,为什么不能在DataRowCollection上使用LINQ

  17. 17

    为什么abc.ABCMeta抽象实例化检查不能用于`list`和`dict`的派生类?

  18. 18

    为什么派生类的构造函数要在C ++中初始化虚拟基类?

  19. 19

    为什么后台工作人员需要在其 DoWork 事件处理程序中使用 Thread.Sleep()?

  20. 20

    为什么在C ++中使用基类指针无法到达派生类的成员函数?它的设计思想是什么?

  21. 21

    是否需要在单例类中使用弱引用?

  22. 22

    范围问题:将帐户凭据存储在promise中的新类对象中,但现在需要在其余类中使用此对象

  23. 23

    如何在基类中使用派生类成员设计我需要的类?

  24. 24

    为什么C ++不允许派生类在初始化列表中使用基类成员?

  25. 25

    为什么在创建模型表单时需要“类元”?

  26. 26

    为什么需要在nodejs中使用path模块?

  27. 27

    为什么我需要在 shareReplay 中使用管道?

  28. 28

    为什么我需要在Android中使用super()?

  29. 29

    为什么我需要在 Django 中使用 SlugField?

热门标签

归档