我使用Python2.7编写Set
数据结构。但是在使用Dict.get
时我很困惑。这是我的代码:
#!/usr/bin/env python
# -*- coding:UTF-8
__author__ = 'shenshijun'
class Node(object):
def __init__(self, key, weight):
"""Constructor for """
self.key = key
self.weight = weight
def __cmp__(self, other):
return cmp(self.key, other.key)
def __str__(self):
return "".join(['Node(key=', str(self.key), ',weight=', str(self.weight), ")"])
__dict = {}
a1 = Node('A', 1)
a2 = Node('A', 2)
__dict[a1] = a1
print a1 == a2
print(__dict.get(a2))
此代码的输出如下:
True
None
所以我猜Python在搜索时使用is
运算符来比较键。有人可以找到真相吗?
我使用的Python:
2.7.5 (default, Mar 9 2014, 22:15:05)
[GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.0.68)]
我刚刚解决了我的问题,但有关在这种情况下如何实施__hash__
的任何建议?
答案 0 :(得分:2)
你在a1和a2上有一个相等,但是它们不是同一个对象,实际上引用已经改变了,所以
print a1 is a2 # False
print(__dict.get(a1)) # Node(key=A,weight=1)
print(__dict.get(a2)) # None
a1与a2不是同一个对象,a1的键引用节点,但不引用a2。
编辑
正如@tobias_k所说,您可以覆盖__hash__
函数以执行不同的方式来存储哈希引用而不是内存地址,例如:
class Node(object):
def __init__(self, key, weight):
"""Constructor for """
self.key = key
self.weight = weight
def __cmp__(self, other):
return cmp(self.key, other.key)
def __str__(self):
return "".join(['Node(key=', str(self.key), ',weight=', str(self.weight), ")"])
def __hash__(self):
return ord(self.key)
__dict = {}
a1 = Node('A', 1)
a2 = Node('A', 2)
__dict[a1] = a1
print a1 == a2 # True
print a1 is a2 # False
print(__dict.get(a1)) # Node(key=A,weight=1)
print(__dict.get(a2)) # Node(key=A,weight=1)
答案 1 :(得分:2)
当您在dictionary中查找某个键时,它不会立即测试是否相等。首先,它检查哈希码,以确定"桶"如果项目应该,那么 它将检查是否相等。
由于你没有实现__hash__
方法,它使用默认的哈希码,即内存地址IIRC,所以它从不首先检查相等性。将此添加到您的课程,然后它将工作
def __hash__(self):
return hash(self.key)
输出:
True
Node(key=A,weight=1)
您还可以向print
和__hash__
函数添加一些__cmp__
语句,以查看这些语句的调用时间和顺序。
附录:值得注意的是,虽然没有编程语言强制要求,但在实施{{1}时总是实施__hash__
或者__eq__
,并且以这样的方式,每当两个对象相等时,它们也具有相同的哈希码(反过来不是必需的)。
有关更多信息,请参阅this related question(对于Java,但对Python有效)。