在抽象基类中定义 @property.setter 会产生 AttributeError
Posted
技术标签:
【中文标题】在抽象基类中定义 @property.setter 会产生 AttributeError【英文标题】:Defining @property.setter in Abstract Base Class gives AttributeError 【发布时间】:2020-03-25 20:40:04 【问题描述】:一个抽象基类Base
有一个名为data
的@abstractmethod
,它也是一个@property
。
问题:有没有办法在Base
类中定义属性setter data.setter
,这样我们就不用在所有子类中重复定义setter方法了(即Foo
)?
在 ABC 中定义 data.setter
时显示 AttributeError 的代码
from abc import ABC, abstractmethod
def reload_data():
return ['hello']
class Base(ABC):
@property
@abstractmethod
def data(self):
pass
@data.setter # <----- AttributeError if this is defined here
def data(self, value):
self._data = value
class Foo(Base):
def __init__(self):
self._data = None
@property
def data(self):
if self._data is None:
self._data = reload_data()
return self._data
# @data.setter # <----- Defining it here avoids AttributeError, but
# def data(self, value): causes code repetition in all the subclasses of Base
# self._data = value
foo = Foo()
foo.data = ['world']
print(foo.data)
【问题讨论】:
你试过docs.python.org/3/library/abc.html#abc.abstractmethod中的例子吗? @jonrsharpe 抱歉,我尝试阅读链接的文档,但缺乏了解如何将其应用于我的问题的知识。在这里的任何帮助将不胜感激! 不需要太多的知识;它显示了一个正在应用的 setter,您只需要更改名称。 @jonrsharpe:遵循文档中的配方并不能解决问题。 那么请给个minimal reproducible example。 【参考方案1】:我不知道是否有办法使用 @property
装饰器来完成,但如下所示“手动”执行似乎可行。
from abc import ABC, abstractmethod
def reload_data():
return ['hello']
class Base(ABC):
@abstractmethod
def _get_data(self):
pass
# Non-abstract.
def _set_data(self, value):
self._data = value
class Foo(Base):
def __init__(self):
self._data = None
# Define inherited abstract method.
def _get_data(self):
if self._data is None:
self._data = reload_data()
return self._data
data = property(_get_data, Base._set_data)
foo = Foo()
foo.data = ['world']
print(foo.data) # ['world']
【讨论】:
以上是关于在抽象基类中定义 @property.setter 会产生 AttributeError的主要内容,如果未能解决你的问题,请参考以下文章