错误说明
鉴于帖子中提供的代码,我实际上并没有看到您是如何获得 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
仅将实例与其他Test
s(或任何具有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 中输入鸭子,但生活中总会有例外。