为什么我可以在Python中调用抽象类方法?

为什么我可以在Python中调用抽象类方法?,python,Python,如果使用抽象方法定义抽象类: import abc class A(abc.ABC): @classmethod @abc.abstractmethod def foo(cls): pass 我无法实例化它(如预期的那样): 但是我可以毫无错误地调用它的抽象方法 >> A.foo() 这种行为是否有记录 在Python 3.6和3.7上测试。foo是一种classmethod,通过类方法可以由类本身直接调用。 通过做 In [3]:

如果使用抽象方法定义抽象类:

import abc


class A(abc.ABC):

    @classmethod
    @abc.abstractmethod
    def foo(cls):
        pass
我无法实例化它(如预期的那样):

但是我可以毫无错误地调用它的抽象方法

>> A.foo()
这种行为是否有记录


在Python 3.6和3.7上测试。

foo
是一种
classmethod
,通过类方法可以由类本身直接调用。
通过做

In [3]: A.foo()  

您并不是在实例化类
A
,而是在类
A

上调用函数
foo

简单地说,
abstractmethod
decorator的文档说明:

具有从ABCMeta派生的元类的类无法实例化,除非其所有抽象方法和属性都被重写

政治公众人物3119说:

无法实例化至少包含一个使用此装饰器声明的方法但尚未重写的类

后来

实现
@abstractmethod
装饰器将函数属性
\uuuu isastractmethod\uuuu
的值设置为True。
ABCMeta.\uuuuu new\uuuuuu
方法将类型属性
\uuuuuu abstractmethods\uuuuuu
计算为具有值为true的
\uuuuu isabstractmethod\uuuuu
属性的所有方法名称的集合。它通过组合基类的
\uuuu abstractmethods\uuuuuuuuuuu
属性,添加新类dict中所有具有true
\uuuuuu isabstractmethod\uuuuuuuu
属性的方法的名称,并删除新类dict中所有不具有true
\uuuuu isabstractmethod\uuuuuuuuu
属性的方法的名称来实现。如果生成的
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu

我对实现部分的解释是,
@abstractmethod
从不阻止调用该方法,而是说该类不能实例化,并且子类仍然是抽象的,除非它重写其所有抽象方法


所以我不会说这是出于设计,但至少是一种假定的副作用。

子类化
abc。abc
表示类
A
不能直接实例化

@abc.abstractmethod
装饰程序在类型/名称解析期间强制检查
a
的任何子类。如果
类subofA(A):
未实现修饰方法,则引发异常

一旦传递了类型/名称解析,abstractmethod装饰器不会阻止您调用该方法。毕竟,如果没有实例,就无法调用该方法,除非它是类方法


通过同时使用
@classmethod
@abstractmethod
装饰
foo
,开发人员可以指定
A.foo()
可以安全调用,而无需实例化类,但是,对
A
进行子类化的任何人都必须实现一个覆盖方法来保持这种行为。

官方python文档ABC:docs.python.org/3/library/ABC.html信息:www.python-course.eu/python3_abstract_classes.php
In [3]: A.foo()