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

使用@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,符合预期

关键修正点

  1. 用_price作为实际存储价格的变量,下划线开头是Python社区的约定,提示这是内部变量,外部代码最好不要直接访问;
  2. getter方法返回self._price,直接读取存储值,不会触发递归;
  3. setter方法把处理后的值赋值给self._price,避免再次触发setter调用;
  4. 初始化时的self.price = price会自动调用setter,所以即使传入负数,也会被自动修正为0,不用在__init__里额外处理。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 20:37:55