我读了this关于抽象类的非常好的文档
abc.ABC
。它有这个例子(我为了这个问题而缩短了):
import abc
class Base(abc.ABC):
@property
@abc.abstractmethod
def value(self):
return 'Should never reach here'
@value.setter
@abc.abstractmethod
def value(self, new_value):
return
class PartialImplementation(Base): # setter not defined/overridden
@property
def value(self):
return 'Read-only'
令我最惊讶的是,
PartialImplementation
可以被实例化,尽管它只覆盖了 getter:
>>> PartialImplementation()
<__main__.PartialImplementation at 0x7fadf4901f60>
天真地,我以为由于接口有两个抽象方法,因此必须在任何具体类中重写这两个方法,这就是文档中所写的:“虽然具体类必须提供所有抽象方法的实现,.. .”。解决方案必须是,我们实际上只有一个抽象名称,
value
,需要实现,并且确实发生在 PartialImplementation
。
有人可以向我正确解释一下吗?
另外,如果不需要实现它,为什么要将 setter 提升到接口?如果在
PartialImplementation
实例上可调用,当前的实现不会执行任何操作。
抽象属性很棘手。你的基类有 one 属性(它本身不是抽象的;它只是有其 getter 和 setter 的抽象方法)。
ABC 机制可以检测给定属性是否分配有一个或多个抽象方法,但它无法判断该属性本身是否被具有无抽象方法的新属性替换。 (本质上,抽象性被融入到属性本身中;
Base.__abstractmethod__
仅表示namevalue
有与之相关的东西。)
您的子类完全定义了一个新属性,即“独立”的继承属性。相反,您需要使用继承属性提供的适当方法来创建一个“基于”继承属性的新属性。
这个类仍然是抽象的,因为只添加了具体的 getter
到新房产。
class PartialImplementation(Base):
@Base.value.getter
def value(self):
return 'Read-only'
这个类是具体的,并且
还提供只读属性。
class PartialImplementation(Base):
@Base.value.getter
def value(self):
return 'Read-only'
@value.setter
def value(self, v):
raise AttributeError("property 'value' has no setter")
请注意,如果我们使用
Base.value.setter
而不是
value.setter
,我们将创建一个新属性,该属性
only为继承的属性添加了一个具体的 setter(它仍然只有一个抽象的 getter)。我们希望使用具体的 getter 将 setter 添加到我们的新属性中。