Python字典存在键但dict.get()返回None的问题求助
问题根源与解决方案
这问题我之前碰过!核心原因是你的Graph.Node对象在被加入字典后,它的x或y属性被修改了,直接打破了Python字典依赖的「哈希不变性」规则。
为什么会出现这种矛盾现象?
字典是基于哈希表实现的:
- 当你把
Node对象作为键存入nodehashes时,Python会用当时的__hash__()结果计算它在哈希表中的存储位置。 - 你的
__hash__是基于self.x和self.y的,一旦这两个属性在存入字典后被修改,这个对象的哈希值就变了。 - 调用
get(key)时,Python会用当前的哈希值去查找,但这个位置根本没有这个键(原位置是用旧哈希存的),所以返回None。 - 而遍历
items()是直接扫描哈希表中所有已存在的键值对,不管当前键的哈希值是否变化,所以能看到正确的键值对。
如何验证这个问题?
在你的循环里加一行打印哈希值的代码,对比对象当前的哈希值和基于x/y计算的哈希值:
for key, value in nodehashes.items(): print(key, nodehashes.get(key), value, hash(key), hash((key.x, key.y)))
如果某个键的后两个哈希值不一样,那就实锤是x或y被修改过了。
解决方案
1. 让x和y变成不可变属性(推荐)
把属性设为只读,从根源上杜绝修改的可能:
class Graph.Node: def __init__(self, x, y): # 用私有变量存储,只通过property暴露读取接口 self._x = x self._y = y @property def x(self): return self._x @property def y(self): return self._y def __eq__(self, other): # 先判断类型,避免和非Node对象比较出问题 if not isinstance(other, Graph.Node): return False return self.x == other.x and self.y == other.y def __hash__(self): return hash((self.x, self.y))
2. 若必须修改属性,修改后更新字典(不推荐)
如果业务逻辑一定要修改x/y,那修改后必须先把旧键从字典中移除,再重新添加:
# 修改属性前先弹出旧键 old_value = nodehashes.pop(node) # 修改node的x或y(注意:如果用了上面的property,需要调整属性的可写性) node._x = new_x # 重新加入字典 nodehashes[node] = old_value
额外小提醒
你的__eq__方法没有判断other的类型,如果不小心和非Graph.Node对象比较,可能会出现奇怪的结果(比如和元组(x,y)相等),加上isinstance判断会更安全。
内容的提问来源于stack exchange,提问作者Jaswant P
相关产品推荐
相关产品推荐

