Python 使用@abstractproperty和@abstractmethod实现/重写的实际差异
考虑一个抽象基类,它有一个您希望每个后续子类重写的函数。使用abc模块和ABCMeta;使用Python 使用@abstractproperty和@abstractmethod实现/重写的实际差异,python,properties,abstract,abc,Python,Properties,Abstract,Abc,考虑一个抽象基类,它有一个您希望每个后续子类重写的函数。使用abc模块和ABCMeta;使用@abstractproperty或@abstractmethod进行装饰是否实际上强制实现的子类/开发人员创建装饰器指定的函数类型?从我的实验中,您可以用方法重写抽象属性,用子类中的属性重写抽象方法 这个概念不正确吗?这个概念是正确的;ABCMeta代码不区分abstractproperty和abstractmethod 这两个装饰器都向装饰项添加了一个属性,\uuu isastractmethod\u
@abstractproperty
或@abstractmethod
进行装饰是否实际上强制实现的子类/开发人员创建装饰器指定的函数类型?从我的实验中,您可以用方法重写抽象属性,用子类中的属性重写抽象方法
这个概念不正确吗?这个概念是正确的;
ABCMeta
代码不区分abstractproperty
和abstractmethod
这两个装饰器都向装饰项添加了一个属性,\uuu isastractmethod\uuuuu
,ABCMeta使用该属性向您定义的ABC添加一个\uuuuuu abstractmethods\uuuu
属性(一个frozenset
)。然后,对象
类型可以防止创建任何类的实例,其中。\uuuuuu abstractmethods\uuuuuu
中列出的任何名称都没有具体的实现。没有对函数和属性进行检查
举例说明:
>>> 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
类将找到更少的方法或属性__IsAbstractMethods属性,从而使生成的\uuuuuuuAbstractMethods\uuuuu
集更小;一旦集合为空,就可以创建这样一个子类的实例
这些检查是在中进行的,不进行与描述符类型匹配的检查:
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
,该子类重写\uuuu new\uuuu
方法,并检查基类上命名的任何抽象方法或属性是否确实与cls
上的非抽象方法或属性匹配。多谢了,证实了我的怀疑。我不认为我应该做override\uuuuu new\uuuuu
,相反,它应该已经像那样工作了。我猜开发人员忽略了这一点,或者你认为他们没有真正检查函数类型是有原因的吗?@Parham:我认为这是一种简化;例如,也没有对函数签名进行测试。我们的目标不是强制实现一个特定的接口,我们的目标是使输入更容易。开发人员仍然负责提供一个有效的实现。好的,这是有意义的。这几乎是我想象的。非常感谢。