使用@abstractproperty和@abstractmethod实现/覆盖的实际差异 [英] Actual difference in implementing/overriding using @abstractproperty and @abstractmethod
问题描述
考虑一个抽象基类,该基类具有一个函数,您希望每个后续子类都重写该函数。使用abc模块和ABCMeta;确实使用 @abstractproperty
或 @abstractmethod
进行修饰实际上迫使子类/开发人员实施以创建由装饰员?通过我的实验,您可以在子类中使用方法覆盖抽象属性,并在子类中覆盖具有属性的抽象方法。
Consider an abstract base class with a function which you want each subsequent subclass to override. Using the abc module and ABCMeta; does decorating with @abstractproperty
or @abstractmethod
actually force the subclass/developer implementing to create the type of function specified by the decorator? From my experiments you can override an abstract property with a method and an abstract method with a property in the subclass.
此概念是否正确?
推荐答案
这个概念是正确的; ABCMeta
代码不能区分抽象属性
和抽象方法
。
The notion is correct; the ABCMeta
code does not distinguish between a abstractproperty
and a abstractmethod
.
这两个装饰器均向装饰项 .__ isabstractmethod __
添加属性,其中 ABCMeta
用于向ABC中添加 .__ abstractmethods __
属性( frozenset
)您定义的。然后, object
类型可以防止创建任何类的实例,而在中列出的任何名称都没有。__abstractmethods __
具体的实现。
Both of these decorators add an attribute to the decorated item, .__isabstractmethod__
, which ABCMeta
uses to add an .__abstractmethods__
attribute (a frozenset
) to the ABC you defined. The object
type then guards against creating an instance of any class where any of the names listed in .__abstractmethods__
does not have a concrete implementation. No checks are made for functions versus properties there.
为了说明:
>>> from abc import *
>>> class C:
... __metaclass__ = ABCMeta
... @abstractmethod
... def abstract_method(self): pass
... @abstractproperty
... def abstract_property(self): return 'foo'
...
>>> C.__abstractmethods__
frozenset(['abstract_method', 'abstract_property'])
通过创建对于子类中的这些新覆盖, ABCMeta
类将使用查找更少的方法或属性。 __isabstractmethod __
属性,从而使生成的 __ abstractmethods __
设置得更小;一旦集合为空,您可以创建此类子类的实例。
By creating new overrides for these in a subclass, the ABCMeta
class will find fewer methods or properties with the . __isabstractmethod__
attribute, thus making the resulting __abstractmethods__
set smaller; once the set is empty you can create instances of such a subclass.
这些检查在 ABCMeta .__ new __
构造函数,并且不进行检查以匹配描述符类型:
These checks are made in the ABCMeta.__new__
constructor and no checks are made to match descriptor types:
cls = super(ABCMeta, mcls).__new__(mcls, name, bases, namespace)
# Compute set of abstract method names
abstracts = set(name
for name, value in namespace.items()
if getattr(value, "__isabstractmethod__", False))
for base in bases:
for name in getattr(base, "__abstractmethods__", set()):
value = getattr(cls, name, None)
if getattr(value, "__isabstractmethod__", False):
abstracts.add(name)
cls.__abstractmethods__ = frozenset(abstracts)
您必须创建一个 ABCMeta
的子类,该子类将覆盖 __ new __
方法,并检查在基类上命名的任何抽象方法或属性是否确实与 cls
上的非抽象方法或属性匹配。
You'd have to create a subclass of ABCMeta
that overrides the __new__
method, and check that any abstract method or property named on a base class is indeed matched with a non-abstract method or property on cls
instead.
这篇关于使用@abstractproperty和@abstractmethod实现/覆盖的实际差异的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!