[英]Why can I call an abstract class method in Python?
If I define an abstract class with an abstract method: 如果我使用抽象方法定义抽象类:
import abc
class A(abc.ABC):
@classmethod
@abc.abstractmethod
def foo(cls):
pass
I can't instantiate it (as expected): 我无法实例化它(如预期):
>>> A()
TypeError: Can't instantiate abstract class A with abstract methods foo
But I can call its abstract method with no errors. 但是我可以正确地调用它的抽象方法。
>> A.foo()
Is this behavior documented somewhere ? 此行为记录在某处吗?
Tested on Python 3.6 and 3.7. 在Python 3.6和3.7上测试。
Nothing is explicit about that. 没有什么是明确的。
Simply the documentation of a the abstractmethod
decorator says: 简单地说,
abstractmethod
装饰器的文档说:
A class that has a metaclass derived from ABCMeta cannot be instantiated unless all of its abstract methods and properties are overridden.
除非实例化了所有抽象方法和属性,否则无法实例化具有从ABCMeta派生的元类的类。
And PEP 3119 says: PEP 3119说:
A class containing at least one method declared with this decorator that hasn't been overridden yet cannot be instantiated.
包含至少一个尚未使用此装饰器声明的方法的类,无法实例化。
and later 然后
Implementation : The
@abstractmethod
decorator sets the function attribute__isabstractmethod__
to the value True.实现 :
@abstractmethod
装饰器将函数属性__isabstractmethod__
设置为True。 TheABCMeta.__new__
method computes the type attribute__abstractmethods__
as the set of all method names that have an__isabstractmethod__
attribute whose value is true.ABCMeta.__new__
方法将类型属性__abstractmethods__
计算为所有具有__isabstractmethod__
属性值为true的方法名称的集合。 It does this by combining the__abstractmethods__
attributes of the base classes, adding the names of all methods in the new class dict that have a true__isabstractmethod__
attribute, and removing the names of all methods in the new class dict that don't have a true__isabstractmethod__
attribute.它通过组合基类的
__abstractmethods__
属性,添加新类dict中具有真实__isabstractmethod__
属性的所有方法的名称以及删除新类dict中不具有真实属性的所有方法的名称来实现此目的。__isabstractmethod__
属性。 If the resulting__abstractmethods__
set is non-empty, the class is considered abstract, and attempts to instantiate it will raiseTypeError
.如果生成的
__abstractmethods__
集为非空,则该类被视为抽象类,并且尝试实例化该类将引发TypeError
。
My interpretation of the implementation part is that @abstractmethod
never prevents the method to be called but only say that that class cannot be instantiated and that a subclass will still be abstract unless it overrides all of its abstract methods. 我对实现部分的解释是,
@abstractmethod
永远不会阻止调用该方法,而只是说该类无法实例化,并且子类将仍然是抽象的,除非它覆盖了其所有抽象方法。
So I would not say that it is by design , but it is at least an assumed side effect. 因此,我不会说这是设计使然 ,但这至少是假定的副作用。
Subclassing abc.ABC
indicates that class A
cannot be instantiated directly. 子类
abc.ABC
指示不能直接实例化类A
The @abc.abstractmethod
decorator forces a check on any subclass of A
during type/name resolution. @abc.abstractmethod
装饰器在类型/名称解析期间强制检查A
任何子类。 If class subofA(A):
does not implement the decorated method, then an exception is raised. 如果
class subofA(A):
未实现修饰的方法,则引发异常。
Once type/name resolution is passed, the abstractmethod decorator does not prevent you from calling the method. 一旦通过类型/名称解析,则abstractmethod装饰器不会阻止您调用该方法。 After all, you aren't able to call the method without an instance, unless it is a class method.
毕竟,没有实例就无法调用该方法,除非它是一个类方法。
By decorating foo
with both @classmethod
and @abstractmethod
you, the developer, specify that A.foo()
is safe to call without instantiating the class, but that anyone who subclasses A
must implement an overriding method to preserve that behaviour. 通过使用
@classmethod
和@abstractmethod
装饰foo
,开发人员可以指定A.foo()
可以安全调用而无需实例化该类,但是子类A
任何人都必须实现重写方法以保留该行为。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.