ABC 是否强制执行方法装饰器?

Do ABCs enforce method decorators?

我正在尝试弄清楚如何确保使用适当的装饰器创建从 ABC 继承的 class 方法。我了解(希望如此)一般情况下 ABC 是如何工作的。

from abc import ABCMeta, abstractmethod

class MyABC(metaclass=ABCMeta):
    @abstractmethod
    def my_abstract_method(self):
        pass

class MyClass(MyABC):
    pass

MyClass()

这给出 "TypeError: Can't instantiate abstract class MyClass with abstract methods my_abstract_method"。太好了,有道理。只需创建一个具有该名称的方法。

class MyClass(MyABC):
    def my_abstract_method(self):
        pass

MyClass()

繁荣。你完成了。但是这个案例呢?

from abc import ABCMeta, abstractmethod

class MyABC(metaclass=ABCMeta):    
    @property
    @abstractmethod
    def my_attribute(self):
        pass

class MyClass(MyABC):
    def my_attribute(self):
        pass

MyClass()

即使 my_attribute 不是 属性,MyClass() 调用仍然有效。我想最后所有 ABC 所做的就是确保存在具有给定名称的方法。而已。如果您想从中获得更多信息,则必须查看 MyABC 的源代码并阅读文档。那里的装饰者和评论会告诉你你需要如何构建你的子class.

我说得对还是我漏掉了什么?

你说得对,ABC 没有强制执行。没有办法强制执行 "has a particular decorator" 之类的东西。装饰器只是 return 对象的函数(例如,property return 是一个 属性 对象)。 ABCMeta 不会做任何事情来确保 class 上定义的属性是特别的;它只是确保它们在那里。这个"works"没有错误:

class MyABC(metaclass=ABCMeta):
    @abstractmethod
    def my_abstract_method(self):
        pass

class MyClass(MyABC):
    my_abstract_method = 2

MyClass()

也就是说,ABCMeta 甚至不能确保 subclass 上提供的抽象方法是一个方法。只需要有一个具有该名称的某种属性,

您当然可以编写自己的元class,它会进行更复杂的检查以确保某些属性具有某些类型的值,但这超出了 ABCMeta 的范围。