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

Python中使用__setattr__时出现AttributeError与RecursionError求助

问题分析与修复方案

第一个版本代码的错误原因

第一个版本中,__init__里执行self._treasure = "gold"时,会自动调用自定义的__setattr__方法。此时self._attributes还未被初始化,__setattr__里访问self._attributes[name] = value就会触发“不存在'_attributes'属性”的警告。

另外,super().__setattr__("_attributes", dict(self.__dict__))逻辑冗余:你已经在修改self._attributes,又通过父类方法重新设置一次,完全没必要,而且此时self.__dict__里还没包含最新的value,反而会导致数据不一致。

第二个版本代码的递归错误原因

修改后的代码里,__setattr__最后执行self._attributes = dict(self.__dict__),这行赋值操作会再次触发__setattr__(因为给实例属性赋值都会调用该方法),形成无限递归,最终导致RecursionError。

修复方案

要实现“treasure属性正常返回'gold',检测到属性新增或修改时输出提示”的目标,需要避免初始化和属性设置时的递归,同时正确维护属性快照。修复后的代码如下:

class Vault:
    def __init__(self):
        # 直接操作__dict__初始化属性,绕过自定义__setattr__,避免递归
        self.__dict__['_treasure'] = "gold"
        self.__dict__['_attributes'] = dict(self.__dict__)

    def __setattr__(self, name, value):
        # 检测属性是否为新增,或已有属性值被修改
        if name not in self._attributes or self._attributes[name] != value:
            print("attribute deleted!")
        # 更新属性快照
        self._attributes[name] = value
        # 调用父类的__setattr__完成实际赋值,避免触发自定义方法的递归
        super().__setattr__(name, value)

    @property
    def treasure(self):
        # 检查当前属性状态与快照是否一致
        if self.__dict__ != self._attributes:
            print("attribute deleted!")
        return self._treasure

关键修复点说明

  1. 初始化阶段:直接操作self.__dict__来设置初始属性,避免触发自定义的__setattr__,确保_attributes能被正常创建并保存初始状态。
  2. __setattr__逻辑:
    • 先判断属性是新增还是值被修改,满足条件时输出提示。
    • 更新_attributes快照后,调用super().__setattr__完成实际属性赋值,这里调用的是父类(object)的原生方法,不会再次触发自定义的__setattr__,避免递归。
  3. treasure属性检查:保留原有的快照对比逻辑,读取属性时如果状态不一致,输出提示。

测试示例

v = Vault()
print(v.treasure)  # 输出: gold(初始状态一致,无提示)

v.new_attr = 123  # 输出: attribute deleted!(新增属性)
v._treasure = "silver"  # 输出: attribute deleted!(修改属性值)
print(v.treasure)  # 输出: attribute deleted! 然后输出: silver(状态不一致触发提示)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 05:55:23