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函数的装饰器来更新旧属性,而不是完全从头开始创建新的属性,则会收到有关未重写抽象方法文本的错误.
标签:abstract-methods,properties,python-3-x,python 来源: https://codeday.me/bug/20191121/2054397.html