为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属性,彻底消除递归 - 修复
xysetter的参数错误(原代码定义两个参数不符合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
相关产品推荐
相关产品推荐

