python-为什么以下代码不会引发错误?

我正在尝试使用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没有实现.为什么没有错误?

最佳答案
基类中text属性的getter和setter都命名为text,因此它们仅在__abstractmethods__集中出现一次.当您在子类中重写getter时,它将“计数”,就好像它也重写了setter一样.

不幸的是,尽管仅使用getter的抽象属性可以很好地工作,但似乎并没有一种优雅的方式来同时具有抽象getter和setter的属性.如果您使用单个名称,则仅需要覆盖该名称(并且您不必像您所发现的那样覆盖该名称).如果为这些函数使用单独的名称,然后使用text = property(_text_get,_text_set),则具体的子类将需要替换所有三样东西(getter,setter和property对象本身).更好的方法可能是使属性本身在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(现已弃用)的文档后,我认为我更好地理解了为什么只读属性没有错误(这并不像我上面所说的那么简单).

不会出现错误的原因是,新属性的“设置”实现与基类的实现不同.当然,该行为是一个例外,但是从技术上讲,这是一种不同的行为,它会覆盖原始设置员的行为.

如果您通过使用@ Base.text.getter作为SubClass中重写的setter函数的装饰器来更新旧属性,而不是完全从头开始创建新的属性,则会收到有关未重写抽象方法文本的错误.

转载注明原文:python-为什么以下代码不会引发错误? - 代码日志