使用@property与@setter装饰器时触发RecursionError的问题排查
解决Phone类中@property和@setter引发的RecursionError问题
嘿,这个递归错误我太熟了!你踩的坑是@property使用时的经典问题——在getter和setter里直接访问了被装饰的属性名,导致无限递归调用。
错误原因拆解
当你用@property装饰price方法后,self.price就不再是普通的实例属性了:
- 每次读取
self.price,都会触发你定义的price()getter方法; - 每次给
self.price赋值,都会触发@price.setter装饰的方法。
看你的代码:
- getter里写
return self.price,这行代码会再次调用getter,无限循环直到超出递归深度; - setter里写
self.price = max(new_value,0),赋值操作又会触发setter,同样陷入死循环。
修正方案:使用内部存储变量
我们需要一个专门用来存储实际值的“内部属性”,Python里通常用下划线开头的变量名(比如_price)来区分它和对外暴露的访问器。修正后的代码如下:
class Phone: def __init__(self, brand, model_name, price): self.brand = brand self.model_name = model_name self.price = price # 这里会自动调用setter,处理负数 @property def price(self): return self._price # 返回内部存储的实际值 @price.setter def price(self, new_value): self._price = max(new_value, 0) # 将处理后的值存入内部变量,避免递归 # 测试正常情况 p1 = Phone('Asus','Asus10',102000) print(p1.price) # 输出 102000 # 测试负数输入 p2 = Phone('Apple','iPhone14', -5000) print(p2.price) # 输出 0,符合预期
关键修正点
- 用
_price作为实际存储价格的变量,下划线开头是Python社区的约定,提示这是内部变量,外部代码最好不要直接访问; - getter方法返回
self._price,直接读取存储值,不会触发递归; - setter方法把处理后的值赋值给
self._price,避免再次触发setter调用; - 初始化时的
self.price = price会自动调用setter,所以即使传入负数,也会被自动修正为0,不用在__init__里额外处理。
内容的提问来源于stack exchange,提问作者root13
相关产品推荐
相关产品推荐

