我正在尝试使用Python 3编写一个抽象类,如下所示:
from abc import *
class Base(metaclass=ABCMeta):
@abstractmethod
def __init__(self, text=''):
self._text = text
@property
@abstractmethod
def text(self):
return self._text
@text.setter
@abstractmethod
def text(self, text):
self._text = text
class SubClass(Base):
def __init__(self, text):
super().__init__(text)
@property
def text(self):
return super().text
q = SubClass("Test")
当我运行文件时,解释器不会抱怨text.setter没有实现。为什么没有错误?
答案 0 :(得分:3)
text
类中Base
属性的getter和setter都被命名为text
,因此它们只在__abstractmethods__
集中出现一次。当您在SubClass
中覆盖getter时,它会计算""好像它也覆盖了二传手。
不幸的是,虽然只有getter的抽象property
工作正常,但似乎并不是一个优雅的方法来拥有一个带有抽象getter和setter的属性。如果您使用单个名称,则只需要覆盖该名称(并且覆盖不需要具有setter,因为您已经发现)。如果对这些函数使用单独的名称然后使用text = property(_text_get, _text_set)
,则具体的子类将需要替换所有三个东西(getter,setter和属性对象本身)。更好的方法可能是让属性本身在Base
类中具体,但让它调用抽象的getter和setter实现函数,这些函数可以是抽象的,以及哪些子类可以轻松覆盖:
@abstractmethod
def _text_get_imp(self):
return self._text
@abstractmethod
_text_set_imp(self, value):
self._text = value
@property
def text(self):
return self._text_get_imp()
@text.setter
def text(self, value)
self._text_set_imp(value)
修改:在今天阅读了(现已弃用)abc.abstractproperty
的文档之后,我想我更了解为什么只读属性没有错误(它并不像我上面说的那么简单)。
您没有收到错误的原因是您的新媒体资源有不同的实施方式"设置"比基类。当然,这种行为是为了引发异常,但这在技术上是一种不同的行为,它会覆盖原始setter的行为。
如果您使用@Base.text.getter
作为SubClass
中被覆盖的setter函数的装饰器更新了旧属性,而不是从头开始创建新的property
,那么您可以得到一个关于抽象方法text
未被覆盖的错误。