第一次在这里发布问题,希望我提问的方式是正确的。
在添加元素到Python字典后,是否可能让Python告诉你是否添加该元素会导致冲突?(以及冲突解决策略在找到放置元素的位置之前探测了多少个位置?)
我的问题是:我正在使用字典作为更大项目的一部分,并且经过广泛的分析,我发现代码最慢的部分是使用字典实现的稀疏距离矩阵。
我正在使用Python对象的ID作为键,这些ID是唯一的整数,因此我知道它们都哈希到不同的值上。但是将它们放入字典中仍然可能会导致冲突。我不认为字典冲突是减慢程序的原因,但我想将其从我的查询中排除。
因此,例如,给定以下字典:
d = {}
for i in xrange(15000):
d[random.randint(15000000, 18000000)] = 0
你能让Python告诉你在创建字典时发生了多少冲突吗?
我的实际代码与应用程序纠缠在一起,但上面的代码生成的字典看起来非常类似于我正在使用的字典。
再说一遍:我不认为冲突是拖慢我的代码的原因,我只想通过显示我的字典没有太多冲突来消除这种可能性。
感谢您的帮助。
编辑:以下是实现@Winston Ewert解决方案的一些代码:
n = 1500
global collision_count
collision_count = 0
class Foo():
def __eq__(self, other):
global collision_count
collision_count += 1
return id(self) == id(other)
def __hash__(self):
#return id(self) # @John Machin: yes, I know!
return 1
objects = [Foo() for i in xrange(n)]
d = {}
for o in objects:
d[o] = 1
print collision_count
请注意,当您在一个类上定义__eq__
时,如果您没有定义__hash__
函数,Python将为您提供一个TypeError: unhashable instance
。我的预期结果与实际运行结果不太一样。如果您的
__hash__
函数返回1
,则会出现大量冲突,就像我所预期的那样(在我的系统上,对于n=1500,有1125560个冲突)。但是,如果使用return id(self)
,则没有冲突。有人知道为什么会显示0个冲突吗?
编辑: 我可能已经解决了这个问题。
这是因为
__eq__
只会在两个对象的__hash__
值相同时才被调用,而不是它们的“压缩版本”(正如@John Machin所说)。
hash(-1)== hash(-2)
。除此之外,区间-sys.maxint-1 <= x <= sys.maxint
中的所有 int 值都具有唯一的哈希值。关于哈希长整型的算法在这里描述:http://effbot.org/zone/python-hash.htm。 - unutbu