我刚刚开始学习 @property 在 Python 中实现 getter 和 setter 方法。我知道为了不让它最终成为 RecursionError,我们必须在本地更改属性名称,例如添加下划线作为前缀。但是当我尝试实现它时,我得到了一个 AttributeError ,它表示对象(子类)缺少我在其超类中更改的特定属性,正如我之前提到的。这是我的代码。
class Handler(ABC):
@property
def parent(self) -> Handler:
return self._parent
@parent.setter
def parent(self, parent: Handler):
self._parent = parent
@abstractmethod
def handle(self):
pass
def add_child(self, child):
pass
class ThingHandler(Handler):
def __init__(self, name):
self.name = name
self.string = self._make_string()
self._children: List[Handler] = list()
def handle(self):
... # method implementation, not important atm.
def add_child(self, child: Handler):
self._children.append(child)
child.parent = self
def __str__(self):
return self.string
def _make_string(self):
name = self.name.lower().replace(" ", "_")
return str(self.parent) + f".{name}"
当我在
ThingHandler
方法中遇到错误(特别是在我调用 self.parent 的最后一行)时,我只是想初始化 _make_string
。错误信息是
AttributeError: 'ThingHandler' object has no attribute '_parent'. Did you mean: 'parent'?
指Handler中的
return self._parent
行。我也在尝试 python 的 ABC,以防它与错误有关。
有什么解决方案/建议吗?
您没有在类构造函数中初始化
_parent
。
您需要定义初始化 __init__
的 self._parent
魔术方法。
class Handler(ABC):
def __init__(self) -> None:
self._parent = None
@property
def parent(self) -> Handler:
return self._parent
@parent.setter
def parent(self, parent: Handler):
self._parent = parent
@abstractmethod
def handle(self):
pass
def add_child(self, child):
pass
这将创建
_parent
属性,您将在稍后的代码中引用该属性。
然后你还需要在子类中运行构造函数,因为你覆盖了它。使用
super()
来实现这一点。
class ThingHandler(Handler):
def __init__(self, name):
super().__init__()
self.name = name
self.string = self._make_string()
self._children: List[Handler] = list()
这将防止构造函数覆盖。