You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为Python的Point类添加计数器成员触发RecursionError问题求助

问题:Point类添加计数器触发RecursionError

尝试给Python的Point类添加计数器成员时,运行触发错误:RecursionError: maximum recursion depth exceeded!,印象中早年Python版本不会出现这个错误。

编辑说明:代码中的id=0行是误写。

原错误代码:

import math
class Point():
#           id=0
            def __init__(self, x, y, z:float=0):
                import sys; print(f"{self.id=}>{sys.getrecursionlimit()}")# maximum recursion depth 1000 exceeded
                self._x = x; self._y = y; self._z = z; self.id+=1
            @property
            def x(self):
                return self._x
            @x.setter# to define a "non-public member"
            def x(self, value):
               self._x=value
            @property
            def y(self):
                return self._y
            @y.setter
            def y(self, value):
               self._y=value
            @property
            def xy(self):
                return [self._x,self._y]
            @xy.setter
            def xy(self,xval,yval):
               self._x=xval;self._y=yval
            @property
            def z(self):
                return self._z
            @z.setter
            def z(self, value):
                self._z=value
            @property
            def id(self):
                return self.id
#    @id.setter
#    def id(self, value): # raise AttributeError("Can't")
#        raise WriteCoordinateError("Point Number id is read-only")
            @property
            def distance(self):
                return round(math.dist((0, 0, 0), (self._x, self._y, self._z)))

错误原因

核心问题出在id的@property定义上:

@property
def id(self):
    return self.id

当访问self.id时,会触发这个property的getter方法,而方法内部又直接返回self.id,这会再次调用getter,形成无限递归,直到达到Python的递归深度上限,抛出RecursionError。

另外,你想实现的是实例计数器,原代码逻辑本身错误:没有定义类级别的计数器变量,试图通过实例的id属性自增,但实例初始化时self.id根本未定义,加上错误的property,直接触发递归。

修复方案

要实现“给每个实例分配唯一ID”或“统计Point实例总数”的需求,需要用类级别的变量维护计数器,同时修正id的property实现:

修正后的代码

import math

class Point():
    # 类级别的计数器,记录已创建的实例总数
    _instance_count = 0

    def __init__(self, x, y, z: float = 0):
        # 给当前实例分配唯一ID,然后递增全局计数器
        Point._instance_count += 1
        self._id = Point._instance_count
        
        self._x = x
        self._y = y
        self._z = z

    @property
    def x(self):
        return self._x

    @x.setter
    def x(self, value):
        self._x = value

    @property
    def y(self):
        return self._y

    @y.setter
    def y(self, value):
        self._y = value

    @property
    def xy(self):
        return [self._x, self._y]

    @xy.setter
    def xy(self, values):
        # 修正setter参数:setter只能接收一个参数,改为接收包含两个值的序列
        xval, yval = values
        self._x = xval
        self._y = yval

    @property
    def z(self):
        return self._z

    @z.setter
    def z(self, value):
        self._z = value

    @property
    def id(self):
        # 返回当前实例的唯一ID
        return self._id

    @property
    def total_instances(self):
        # 返回已创建的实例总数
        return Point._instance_count

    @property
    def distance(self):
        return round(math.dist((0, 0, 0), (self._x, self._y, self._z)))

关键修改点

  • 添加类变量_instance_count维护全局计数,避免实例间计数混乱
  • 实例初始化时给self._id赋值,确保每个实例有唯一ID
  • 修正id的property,返回实例的_id属性,彻底消除递归
  • 修复xy setter的参数错误(原代码定义两个参数不符合setter语法,改为接收包含两个值的序列)

测试示例

p1 = Point(1,2)
print(p1.id)  # 输出1
print(p1.total_instances)  # 输出1

p2 = Point(3,4,5)
print(p2.id)  # 输出2
print(p2.total_instances)  # 输出2

内容的提问来源于stack exchange,提问作者MathArt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 15:56:18