我正在尝试使用 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 没有实现。为什么没有报错?
最佳答案
Base
类中 text
属性的 getter 和 setter 都被命名为 text
,因此它们只在 中出现一次>__abstractmethods__
设置。当您覆盖 SubClass
中的 getter 时,它“算”为好像它也覆盖了 setter。
不幸的是,虽然只有 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
没有被覆盖的错误。
关于python - 为什么下面的代码不会抛出错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23435259/