Python类中同时存在__getattribute__和__getattr__时,为何会出现意外的shape属性?
为什么你的实例里突然多了个
shape属性? 嘿,这个问题其实和你的代码逻辑本身关系不大,罪魁祸首是PyCharm的调试器!让我给你拆解一下整个过程:
首先,先回忆你写的__getattr__方法的特性:当你访问一个实例上不存在的属性时,Python会自动调用这个方法。而你的__getattr__逻辑更“激进”——只要碰到不存在的属性,就直接用__setattr__把这个属性加到实例上,值设为'fred'。
那shape是哪来的?PyCharm的调试器在展示实例详情的时候,会偷偷尝试访问一些常见属性(比如shape,这个属性在numpy数组、PyTorch张量这类数据结构里很常见),用来判断实例的类型或者补充显示信息。当调试器访问x.shape时,这个属性原本根本不存在于你的X实例里,所以直接触发了你写的__getattr__方法,于是shape就被自动添加到了实例上,值就是你设置的'fred'。
你可以做个小实验验证这个结论:
- 不要用调试模式,直接运行代码然后打印
dir(x),你会发现只有count属性,完全看不到shape; - 或者在
__getattr__里加一行打印日志:
启动调试后,你会在控制台看到调试器触发了对def __getattr__(self, item): print(f"触发__getattr__:访问属性{item}") return self.__setattr__(item, 'fred')shape的访问记录。
另外提个小建议:你的__getattr__实现会给所有不存在的属性自动赋值,这在调试场景很容易被工具触发产生意外属性。如果你的需求只是处理特定属性,最好加个判断,比如:
def __getattr__(self, item): if item == 'target_attr': value = 'fred' self.__setattr__(item, value) return value # 其他属性抛出正常的AttributeError,避免干扰调试工具 raise AttributeError(f"'X' object has no attribute '{item}'")
内容的提问来源于stack exchange,提问作者swright573
相关产品推荐
相关产品推荐

