Python如何将对象引用作为字典key且无需自定义__hash__和__eq__方法
问题解答
Python 支持直接将自定义类实例的引用作为字典的 key,且默认行为就可以满足你的需求,不需要自定义 __hash__ 和 __eq__ 方法。
核心原理
用户自定义类的实例默认自带的 __hash__ 和 __eq__ 方法基于对象的唯一内存身份(即 id() 函数的返回值)实现:
- 哈希值计算只和对象的内存地址绑定,和实例内部的属性无关
- 相等判断默认等价于
is运算符,仅当两个变量指向同一个内存地址的对象时才返回 True
这种情况下,无论你修改实例的任意属性,只要实例本身还是同一个内存地址的对象,作为字典 key 的身份就不会发生变化,完全可以正常索引到对应的值。
示例代码
你只需要删除你代码中自定义的 __hash__ 和 __eq__ 方法即可正常运行:
class Example: def __init__(self, id): self.id = id # 创建实例 obj = Example("My object") # 直接作为字典key instances = {obj: 1} # 修改实例属性 obj.id = "Not my object" # 依然可以正常获取对应值 print(instances[obj]) # 输出 1
原代码问题原因
你当前遇到修改属性后字典找不到 key 的问题,正是因为你主动重写了 __hash__ 和 __eq__ 方法,把哈希和相等判断的逻辑绑定到了可变的 id 属性上。这违反了字典对 key 的核心要求:对象作为字典 key 存在的生命周期内,其哈希值必须保持不变。当你修改 id 属性后,实例的哈希值发生了变化,自然无法匹配到字典中原来的存储槽位。
可选替代方案
如果你后续需要同时支持「按属性判断实例相等」和「按实例引用作为 key」的需求,也可以不修改类定义,直接用实例的内存 id 作为字典的 key:
obj = Example("My object") instances = {id(obj): 1} obj.id = "Not my object" print(instances[id(obj)]) # 输出 1
内容的提问来源于stack exchange,提问作者Jared Wogan
相关产品推荐
相关产品推荐

