Python 使用@abstractproperty和@abstractmethod实现/重写的实际差异

Python 使用@abstractproperty和@abstractmethod实现/重写的实际差异,python,properties,abstract,abc,Python,Properties,Abstract,Abc,考虑一个抽象基类,它有一个您希望每个后续子类重写的函数。使用abc模块和ABCMeta;使用@abstractproperty或@abstractmethod进行装饰是否实际上强制实现的子类/开发人员创建装饰器指定的函数类型?从我的实验中,您可以用方法重写抽象属性,用子类中的属性重写抽象方法 这个概念不正确吗?这个概念是正确的;ABCMeta代码不区分abstractproperty和abstractmethod 这两个装饰器都向装饰项添加了一个属性,\uuu isastractmethod\u

考虑一个抽象基类,它有一个您希望每个后续子类重写的函数。使用abc模块和ABCMeta;使用
@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:我认为这是一种简化;例如,也没有对函数签名进行测试。我们的目标不是强制实现一个特定的接口,我们的目标是使输入更容易。开发人员仍然负责提供一个有效的实现。好的,这是有意义的。这几乎是我想象的。非常感谢。