我试图找出如何确保使用适当的装饰器创建从ABC继承的类的方法。我(希望)了解ABCs的工作原理。
from abc import ABCMeta, abstractmethod
class MyABC(metaclass=ABCMeta):
@abstractmethod
def my_abstract_method(self):
pass
class MyClass(MyABC):
pass
MyClass()
这给出了" TypeError:不能用抽象方法my_abstract_method"来实例化抽象类MyClass。很棒,很有意义。只需创建一个具有该名称的方法。
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()调用仍然有效。我想最终所有ABCs都确保存在具有给定名称的方法。而已。如果您想从中获得更多,您必须查看MyABC的源代码并阅读文档。那里的装饰器和注释将告诉您如何构建子类。
我是否正确或我在这里遗漏了什么?
答案 0 :(得分:1)
你是正确的,ABCs不强制执行。没有办法强制执行“有一个特定的装饰者”之类的东西。装饰器只是返回对象的函数(例如,property
返回一个属性对象)。 ABCMeta没有做任何事情来确保类中定义的属性是特别的;它只是确保他们在那里。这“无效”:
class MyABC(metaclass=ABCMeta):
@abstractmethod
def my_abstract_method(self):
pass
class MyClass(MyABC):
my_abstract_method = 2
MyClass()
也就是说,ABCMeta甚至不确保子类提供的抽象方法是一个方法。只需要有一个具有该名称的属性,
你当然可以编写自己的元类来进行更复杂的检查,以确保某些属性具有某些类型的值,但这超出了ABCMeta的范围。