当__dict__被重写时,能否获取对象的真实__dict__?是否存在更简便的解决方案?
当__dict__被重写时,能否获取对象的真实__dict__?是否存在更简便的解决方案?
嘿,这个问题真的挺有意思的!你观察得完全没错——哪怕在类里把__dict__硬设成了空字典,对象的属性该怎么用还是怎么用,这说明Python内部根本没把你定义的那个__dict__当回事,它依然在用自己给实例分配的真实字典来存属性,只是我们通过obj.__dict__访问到的是被覆盖的类属性而已。
背后的原理
在Python里,当你在类层级定义__dict__时,它会变成一个类属性,而不是实例专属的字典。每个实例创建时,Python都会自动给它分配一个真正的实例字典,用来存储该实例独有的属性。但当你访问obj.__dict__时,因为类里有同名的属性,Python会优先返回类的__dict__,而不是实例的真实字典——这就是为什么你看到obj.__dict__是空的,但obj.hacky却能正常取值的原因。
获取真实__dict__的方法
想要拿到实例的真实字典,其实有几种靠谱的方式,其中不乏简便的方案:
最简便的方案:用object.__getattribute__
object是所有Python类的基类,它的__getattribute__方法可以绕过类中定义的同名属性,直接获取实例的真实属性。一行代码就能搞定:
class MyClass: __dict__ = {} obj = MyClass() obj.hacky = 5 # 获取实例的真实字典 real_dict = object.__getattribute__(obj, '__dict__') print(obj.hacky, obj.__dict__, real_dict) # 输出结果:5 {} {'hacky': 5}
其他备选方案(相对繁琐)
如果你想绕开object的方法,也可以用gc模块的get_referents函数,但需要导入模块,步骤更麻烦:
import gc class MyClass: __dict__ = {} obj = MyClass() obj.hacky = 5 # 通过gc模块获取真实字典 real_dict = gc.get_referents(obj)[0] print(real_dict) # 输出:{'hacky': 5}
不过这个方法依赖垃圾回收机制的内部实现,不如第一种方法通用和直观。
总结
最简便的解决方案无疑是object.__getattribute__(obj, '__dict__'),不需要额外导入模块,逻辑直接清晰,完全能满足需求。
备注:内容来源于stack exchange,提问作者FamousSnake
相关产品推荐
相关产品推荐

