这个 Python 程序的错误是啥?
Posted
技术标签:
【中文标题】这个 Python 程序的错误是啥?【英文标题】:What is the bug in this Python program?这个 Python 程序的错误是什么? 【发布时间】:2021-07-26 12:39:38 【问题描述】:以下源代码中的错误是什么? 我自己找不到。
ShapeBase.py
from abc import ABC
class ShapeBase(ABC):
def __init__(self, idd: str):
self.id_: str = idd
self.cx_: float = 0.0
self.cy_: float = 0.0
@property
def cx_(self) -> float:
return self.cx_
@cx_.setter
def cx_(self, cx: float):
self.cx_ = cx
@property
def cy_(self) -> float:
return self.cy_
@cy_.setter
def cy_(self, cy: float):
self.cy_ = cy
def id(self) -> str:
return self.id_
def area(self) -> float:
pass
Square.py
from shapes.ShapeBase import ShapeBase
class Square(ShapeBase):
def __init__(self, idd: str, a: float):
super().__init__(idd)
self.a_ = a
def area(self) -> float:
return self.a_ * self.a_
def width(self) -> float:
return self.a_
main.py
from shapes.Square import Square
if __name__ == '__main__':
s1 = Square('S1', 4.0)
print("Area = " + str(s1.area()))
输出
C:\Users\pc\AppData\Local\Microsoft\WindowsApps\python3.7.exe C:/Users/pc/source/repos/Shapes/main.py
Process finished with exit code -1073741571 (0xC00000FD)
顺便说一句,这个问题与属性的名称无关。
这个问题与继承有关。
【问题讨论】:
重复的含义是你已经结束了一个无限循环的递归。尝试找出某个东西在哪里调用自己(也许通过调用其他最终调用原始对象的东西)。 尝试在 pycharm 中重新配置您的 python 解释器并将其设置为 python.exe。您可以通过使用where python
命令获取python.exe 的位置
我遇到了另一个异常,E RecursionError: maximum recursion depth exceeded !!! Recursion detected (same locals & position)
。 in __init__ super().__init__(idd) in __init__ self.cx_: float = 0.0 in cx_ self.cx_ = cx in cx_ self.cx_ = cx
所以从@Guy 的评论来看,你有一个问题,self.cx_
最终一遍又一遍地调用自己。
问题出在 setter 和 getter 上。当在 cx_.setter 中时,你会一次又一次地调用相同的 cx_.setter,这会导致递归错误
【参考方案1】:
当您在同一个 setter 函数中调用 self.cx_ = cx
时,您的 cx_
属性正在调用 cx_.setter
。要解决此问题,您需要重命名 __init__
中的属性或删除属性声明,因为您的属性与普通 python 默认值所做的相同。
这是重命名了内部属性的代码
from abc import ABC
class ShapeBase(ABC):
def __init__(self, idd: str):
self.id_: str = idd
self._cx_: float = 0.0
self._cy_: float = 0.0
@property
def cx_(self) -> float:
return self._cx_
@cx_.setter
def cx_(self, cx: float):
self._cx_ = cx
@property
def cy_(self) -> float:
return self._cy_
@cy_.setter
def cy_(self, cy: float):
self._cy_ = cy
def id(self) -> str:
return self.id_
def area(self) -> float:
pass
【讨论】:
self.cx_
和 cx
的名字怎么相同?
我无法理解您想要做什么。属性的名称是cx_
,这与__init__
中定义的名称冲突,这也是cx_
,所以我将__init__
中的名称重命名为_cx_
。 cx
是函数的参数,与错误无关【参考方案2】:
https://pythonguide.readthedocs.io/en/latest/python/property.html#managing-attributes
阅读重要的方框:
"如果我们使用'return self.radius'而不是'return self._radius',那么@property将导致无限循环,因为self.property会调用property方法,该方法将返回self.property,结果再次调用@property。”
循环如下:
@property
def cx_(self) -> float:
return self.cx_
@cx_.setter
def cx_(self, cx: float):
self.cx_ = cx
【讨论】:
好的。但是,这是为什么呢? 因为事情没有按照你的意愿工作。它正在调用属性读取方法。而不是您在__init__
中设置的变量
因为 self.cx_ = value -> 调用属性设置器 cx_.setter -> 属性设置器调用 self.cx_ 再次调用设置器。 self.cx_ = value -> setter cx_.setter -> self.cx_ = value -> setter cx_.setter 等等。当您阅读时也是如此: self.cx_ 调用 getter 执行 self.cx_ 再次调用 getter 等等。【参考方案3】:
我可以在“ShapeBase”类中看到你没有继承 ABC 类的构造函数,尽管你从 ShapeBase 类继承了 ABC 类。
您应该像下面的代码块那样继承基类构造函数。
super().__init__()
或者,
ABC.__init__(self)
还需要传递 ABC 构造函数参数。
【讨论】:
以上是关于这个 Python 程序的错误是啥?的主要内容,如果未能解决你的问题,请参考以下文章