错误说明
鉴于帖子中提供的代码,我实际上并没有看到您是如何获得 KeyError 的,因为您应该收到一个 AttributeError (假设这str(other,name)是一个错字str(other.name))。AttributeError 来自__eq__将 self 的名称与 other 的名称进行比较时的方法,因为您在查找期间的键hash(str('abc')), 是一个 int/long,而不是一个Test对象。
在字典中查找键时,执行的第一个操作是使用键的__hash__方法获取键的哈希。其次,如果 dict 中存在此哈希的值,__eq__则调用键的方法以将键与找到的任何值进行比较。这是为了确保在具有相同哈希的事件对象存储在字典中(通过开放寻址)时,检索到正确的对象。平均而言,此查找仍然是 O(1)。
一步一步看,hash(str('abc'))和的哈希值obj是相同的。在Test中,您定义__hash__为字符串的散列。使用 执行查找时test_Dict[hash(str('abc'))],您实际上是在查找散列的散列,但这仍然很好,因为 int 的散列本身在 python 中。
根据您定义的__eq__方法比较这两个值时,您比较的是对象的名称,但您要比较的值是一个 int ( hash(str('abc'))),它没有name属性,因此引发了 AttributeError。
解决方案
首先,在执行实际的 dict 查找时,您不需要(也不应该)调用hash(),因为该键也作为第二个参数传递给您的__eq__方法。所以
test_Dict[hash(str('abc'))].name
应该成为
test_Dict[str('abc')].name
要不就
test_Dict['abc'].name
因为调用str()字符串文字没有多大意义。
其次,您需要编辑您的__eq__方法,使其考虑到other您要比较的对象的类型。您对此有不同的选择,具体取决于您将Test实例作为键存储在同一个字典中的其他内容。
如果您打算Test仅将实例与其他Tests(或任何具有name属性的对象)一起存储在字典中,那么您可以保留当前拥有的
def __eq__(self, other):
return str(self.name) == str(other.name)
因为您保证您在 dict 中与之比较的所有其他键都是类型Test并且具有name.
如果您打算将字典中的实例与字符串混合,则必须检查您比较的对象是否为字符串,因为字符串在 python 中Test没有属性。name
def __eq__(self, other):
if isinstance(other, str):
return str(self.name) == other
return str(self.name) == str(other.name)
如果您打算将 s 和任何其他类型的对象混合用作键Test,则需要检查该other对象是否具有name要比较的对象。
def __eq__(self, other):
if hasattr(other, "name"):
return str(self.name) == str(other.name)
return self.name == other # Or some other logic since here since I don't know how you want to handle other types of classes.
我不是最后两个的粉丝,因为你有点反对用那些在 python 中输入鸭子,但生活中总会有例外。