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

当__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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.17 10:04:36