以下代码给出了一条错误消息:
class Test(object):
def __init__(self, test = 0):
self.test = test
if __name__ == '__main__':
t1 = Test(1)
t2 = Test(2)
t3 = Test(3)
t4 = Test(1)
my_dict = {}
my_dict[t1] = 1
my_dict[t2] = 2
my_dict[t3] = 3
print(my_dict[t4])
Traceback (most recent call last):
File "C:\Users\Alexander\Documents\Visual Studio 2015\Projects\PipeProcessTest
\PipeProcessTest\DictionaryKeys.py", line 16, in <module>
print(my_dict[t4])
KeyError: <__main__.Test object at 0x0000000002F18080>
Run Code Online (Sandbox Code Playgroud)
这是因为python将t1和t4视为不同的对象.但是,当我使用以下代码实现比较运算符' eq '时:
def __eq__(self, other):
if self.test == other.test:
return True
else:
return False
Run Code Online (Sandbox Code Playgroud)
我收到另一条错误消息,"unhashable type:'Test'"告诉我现在字典不能散列Test对象.我该如何解决这个问题,以便Python能够识别t1和t4是否相同,还能够对Test对象进行哈希处理?
1. 这是因为python将t1和t4视为不同的对象。但是,当我使用以下代码实现比较运算符“eq”时:
当您在 python 中执行以下操作时....
class Test(object):
def __init__(self, test = 0):
self.test = test
if __name__ == '__main__':
t1 = Test(1)
t2 = Test(2)
t3 = Test(3)
t4 = Test(1)
my_dict = {}
my_dict[t1] = 1
my_dict[t2] = 2
my_dict[t3] = 3
Run Code Online (Sandbox Code Playgroud)
这意味着您实际上是在尝试创建一个dict以键为Test对象的对象,Python 首先会检查它们是否keys存在hashable。
objectPython 中的Any是hashable当它integer为obj.__hash__()方法返回任何值时。在 python 中,默认情况下所有用户定义的类都会获得一些哈希值,即id(self).
显然,当你获得id价值时hash,它们看起来会像这个价值8772302607193。因此,如果我们使用这些 id 构建hash表,它可能看起来像这样..
让我们假设 id 是这样的..
id(t1) = 1
id(t2) = 4 # These are just assumptions.
id(t3) = 10 # actual id's are long values.
id(t4) = 20
Run Code Online (Sandbox Code Playgroud)
这就是hash表的构造方式....
hash Actual
value value
------------------
| 1 | t1 |
------------------
| 2 | NULL |
------------------ # Consider that you've respective values are
| 3 | NULL | # here, just for representation I've mentioned
------------------ # t1, t2, t3, t4, ..
| 4 | t2 |
------------------
|
|
------------------
| 10 | t3 |
------------------
|
SO ON
Run Code Online (Sandbox Code Playgroud)
像这样你的hash表被构建,所以当你尝试获得值的t4时候my_dict[t4]。根据假设哈希值为,首先通过调用python 检查 的hash值。t4t4.__hash__()t420
获取哈希值后,20它会检查索引为 20 的哈希表,因为我们没有使用20Python插入任何值只会引发KeyError异常,这就是您KeyError在尝试时得到的原因my_dict[t4]。
这里的另一个场景:
如果您尝试覆盖__hash__方法 fTest类并继续执行您在下面所做的相同操作..
class Test(object):
def __init__(self, test = 0):
self.test = test
def __hash__(self):
self.test # You are just returning the same value
if __name__ == '__main__':
t1 = Test(1)
t2 = Test(2)
t3 = Test(3)
t4 = Test(1)
my_dict = {}
my_dict[t1] = 1
my_dict[t2] = 2
my_dict[t3] = 3
Run Code Online (Sandbox Code Playgroud)
由于我们有overloadedhash 方法返回与初始化相同的值,下面是我们得到的散列值
t1 = 1 , t2 = 2, t3 = 3, t4 = 1
Run Code Online (Sandbox Code Playgroud)
这就是hash当我们有多个值时 table 的样子same hash value。
hash Actual
value value
------------------
| 1 | [t1,t4] | # List of values for the same hash value.
------------------
| 2 | t2 |
------------------ # Consider that you've respective values are
| 3 | t3 | # here, just for representation I've mentioned
------------------ # t1, t2, ...
| 4 | NULL |
------------------
|
SO ON
Run Code Online (Sandbox Code Playgroud)
在这种情况下当您尝试获取时my_dict[t4],如前所述首先检查t4.__hash__()返回的哈希值1。现在 Python dict 检查index1 中的 1hash table并获得多个值[t1, t4]。
在这种情况下,__eq__当您有多个具有相同hash value. 你可以像下面这样做来避免这种情况......
class Test(object):
def __init__(self, test = 0):
self.test = test
def __hash__(self):
return self.test
def __eq__(self, other):
return self is other
Run Code Online (Sandbox Code Playgroud)
在您的情况下,您只需要验证self.test值即可获取对象...
class Test(object):
def __init__(self, test = 0):
self.test = test
def __hash__(self):
return self.test
def __eq__(self, other):
return other.test == self.test
Run Code Online (Sandbox Code Playgroud)
这就是您可以管理 dict 值的方式!