What hash algorithm does Python's dictionary mapping use?
我正在搞一个命令行解析器,想知道python dict使用哪种哈希算法?
我的设置方法是,有一个模式匹配算法,该算法将带标记的输入序列与字典键进行匹配。 一些键相对较长(6到7个字符串的长度为5或6个元组)。 我想知道是否存在长字典键会大大降低键检索效率的问题。
-
看一下这个问题。 它具有指向此页面的链接,该页面描述了python如何对某些不同类型的哈希进行哈希处理,可能会对您有所帮助。
-
看一下Objects / dictnotes.txt
-
PEP 456修改了许多现代哈希代码,在此处记录:python.org/dev/peps/pep-0456。 答案是:可以使用多个哈希函数,具体取决于编译参数和字符串大小。
它使用的哈希取决于用作键的对象-每个类都可以定义自己的__hash __()方法,并且它为特定实例返回的值是用于字典的值。
Python本身为str和tuple类型提供了哈希实现。 快速查看源代码,应该可以找到针对这些源代码的确切算法。
元组的哈希值基于其内容的哈希值。 该算法本质上是这样(略有简化):
1 2 3 4 5 6 7
| def hash(tuple):
mult = 1000003
x = 0x345678
for index, item in enumerate(tuple):
x = ((x ^ hash(item)) * mult) & (1<<32)
mult += (82520 + (len(tuple)-index)*2)
return x + 97531 |
对于字符串,解释器还会遍历每个字符,并将它们与此(再次略微简化)的算法结合起来:
1 2 3 4 5
| def hash(string):
x = string[0] << 7
for chr in string[1:]:
x = ((1000003 * x) ^ chr) & (1<<32)
return x |
更大的问题是要避免散列冲突。 碰撞的哈希键将导致线性搜索,因为字典会尝试查找存储新对象的位置(这已被视为安全问题,并且在即将发布的python版本中行为可能会发生变化)
-
哦好的。由于某种原因,我认为python只是对所有数据类型使用了通用字节码哈希算法。就冲突的哈希键而言,我认为这不会成为问题,因为我拥有的键的数量(相对)很小,可能只有数千个。请原谅我,但是冲突哈希和线性搜索如何成为安全问题?
-
@Joel Cornett:这是一个安全问题,因为哈希表使用存储桶来存储密钥,并且具有相同哈希码的密钥将被哈希到同一存储桶中,从而迫使哈希表每次搜索密钥时都要进行线性搜索,如果密钥数量很大,这可能效率很低(甚至可能导致拒绝服务)。如果程序遇到具有散列到相同散列码的不同键的散列表,则可能导致拒绝服务攻击。
-
如果攻击者可以控制词典中使用的密钥,则他们可能能够插入成百上千个冲突的密钥,从而使插入操作非常缓慢。在某些情况下,这可能导致计算机无响应或数据库不可用-Dos攻击
-
是否有发动此类攻击的记录案例?除最简单的系统外,似乎很难对付所有其他系统,甚至在没有白盒知识的情况下也更加困难。
-
我所讨论的第一个攻击场景是针对Web服务的-如果POST变量以键入其名称的字典结尾,则攻击者可以完全控制这些密钥,并且可以使用足够的变量任意降低服务器的速度。不过,我不知道野外是否有这种攻击。
-
string_hash函数引发TypeError。在Python中,左移运算符用于查找整数,而不是字符串。您如何重构它以便在Python中运行?
-
仅供参考,报告的错误是bugs.python.org/issue13703(哈希冲突安全问题),指向此问题的电子邮件线程在此处mail.python.org/pipermail/python-dev/2011-December/115116.ht ml,引用在混沌通信大会上的演讲。
-
所描述的哈希函数实际上没有任何意义。假设您使用ord将每个字符转换为ASCII版本,那么看起来就很好,直到&(1 << 32)。因为要查找结果中设置的所有位,并且要在(0b100000000000000000000000000000000000000)中设置位,所以总会得出0。