python集的散列如何工作[重复]

Posted

技术标签:

【中文标题】python集的散列如何工作[重复]【英文标题】:How does hashing work for python sets [duplicate] 【发布时间】:2016-11-02 14:06:24 【问题描述】:

我完全熟悉哈希表和哈希的工作原理,但我正在尝试完全理解 O(1) 的来源。

set1 = 's','t'
print('x' in set1)
print('s' in set1)
set2 = 's'
print('s' in set2)

我被告知要检查's'是否在set1中,如果将检查's'的哈希的内存分配,并检查它是否在set1中O(1)并返回布尔值。因此有两个 O(1) 操作,但我的问题是:哈希实际上是如何深入工作的。我的意思是,当您散列's' 时,该散列是否具有set1set2 之类的内容,并且您正在检查set1 是否是set1set2,或者是否每个集合有一个不同的 's' 哈希值,您正在检查每个不同集合的 's' 哈希值。

【问题讨论】:

我对你的问题有点困惑……你能试着改进一下吗? 散列's' 意味着做hash('s')set1set2 与此无关。 set 类型使用该操作的结果来获取其内部表中的索引。 所有可散列对象都有散列方法。该集合使用散列来确定对象在集合中是否唯一。当您测试'x' in set1 时——您正在测试'x' 是否是set1 的成员 " 在一个集合中,Python 会跟踪每个哈希值,当你 if x in values: 时,Python 将获取 x 的哈希值,在内部结构中查找它,然后只将 x 与与 x 具有相同哈希值的值进行比较。”这是我在可能的重复页面中寻找的句子,但我不完全理解。有人可以重新措辞吗?你如何只比较具有相同哈希的事物?这就像像列表一样比较集合中的所有内容,但只检查它们是否相同。 o > o 【参考方案1】:

Python dict 本质上是一个hash table。本质上,键通过散列函数转换为表位置;由于多个键可能具有相同的值,因此必须有某种机制来检测冲突(多个键具有相同的值)并向下移动一系列备用条目,直到找到正确的键。

对于dict,密钥单元格在找到时与一个值相关联。对于set,没有值:一个键要么属于集合,要么不属于。

因此,散列行为允许在恒定时间内消除大多数可能的值(假设冲突不会频繁出现问题,并且 Python 会在可能发生时重新分配存储)。

【讨论】:

【参考方案2】:

我建议你阅读这个previous question,它将详细解释Python中的哈希。

【讨论】:

【参考方案3】:

当 Python 创建字符串时,它是基于字符串值的。因此,分配给不同变量的's''s' 具有相同的哈希值。因此:

>>> a = 's'
>>> b = 's'
>>> hash(a) == hash(b)
True

但是,请注意,它们可能并不总是指向内存中的同一个字符串:

>>> a = 'this is some really long string'
>>> b = 'this is some really long string'
>>> id(a)
47002352L
>>> id(b)
47002608L

【讨论】:

【参考方案4】:

一个(不可变的)对象在其整个生命周期内总是具有相同的哈希值。 set1set2 之间的哈希值相同——这允许像 unionintersection 这样的操作在集合之间发生,以及确定一个成员在集合中是否是唯一的,等等.

>>> first_dict = "s":"s".__hash__(), "t":"t".__hash__()
>>> second_dict = "s":"s".__hash__()
>>> first_dict
's': -638743784, 't': 711199131
>>> second_dict
's': -638743784

您可以在内存中拥有相同的字符串,它们是不同的对象。但由于它们是相同的字符串,它们的哈希值相同。

>>> id(a)
7858120
>>> id(b)
7858624
>>> a.__hash__()
-1117164856
>>> b.__hash__()
-1117164856

一个对象是可哈希的,如果它有一个在其生命周期内永远不会改变的哈希值(它需要一个 hash() 方法),并且可以与其他对象进行比较(它需要一个 eq() 方法)。比较相等的可散列对象必须具有相同的散列值。

哈希性使对象可用作字典键和集合成员,因为这些数据结构在内部使用哈希值。

所有 Python 的不可变内置对象都是可散列的,而没有可变容器(例如列表或字典)是可散列的。默认情况下,作为用户定义类实例的对象是可散列的;它们都比较不相等(除了它们自己),它们的哈希值来自它们的 id()。

【讨论】:

以上是关于python集的散列如何工作[重复]的主要内容,如果未能解决你的问题,请参考以下文章

设计一个重新散列函数......如何避免相同的散列?

如何合并散列数组以获取值数组的散列

如何在python中实现一个好的__hash__函数[重复]

如何设计一个工业级的散列函数?

如何根据散列中的键/值查找键/值数据并将其添加到 Redis 中的散列?

如何将扫描的图像缩小为一致的散列?