这个 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_

ma​​in.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 程序的错误是啥?的主要内容,如果未能解决你的问题,请参考以下文章

所以在我的python代码运行后,我输入输入,程序就停止了。不知道逻辑错误是啥[关闭]

这个 Python 2.x 程序的输出是啥? [复制]

这个错误的原因是啥

这个错误是啥意思?

pascal exitcode=255 是啥错误?

是啥导致了这个 QT 4.7.3 错误?