Python:内置数字类型、字符串的“哈希”值是否标准化?

Python:内置数字类型、字符串的“哈希”值是否标准化?,python,Python,我在思考set、frozenset和dict的顺序时提出了这个问题。Python不保证任何排序,任何排序都在某种程度上与哈希值耦合。但是,数字或字符串内置类型的值的哈希值是否标准化?换句话说,我会 hash((a,b,c,d,e,f,g)) 如果a,b,c,d,e,f,g是数值或str?python的hash()函数执行一组预定义的操作以得出其值。进一步解释了这些操作的含义:给定的对象(字符串、整数等)将始终生成相同的哈希值 当您将项目放入集合(或类似结构)时,只要集合的大小达到某个阈值,它们

我在思考
set
frozenset
dict
的顺序时提出了这个问题。Python不保证任何排序,任何排序都在某种程度上与
哈希值耦合。但是,数字或字符串内置类型的值的哈希值是否标准化?换句话说,我会

hash((a,b,c,d,e,f,g))
如果
a
b
c
d
e
f
g
是数值或
str

python的
hash()
函数执行一组预定义的操作以得出其值。进一步解释了这些操作的含义:给定的对象(字符串、整数等)将始终生成相同的哈希值


当您将项目放入集合(或类似结构)时,只要集合的大小达到某个阈值,它们就会重新刷新。因此,虽然您可能无法预测某组项目的顺序,但相同的n个项目在一组项目中的顺序始终相同

因此,实际上是的<代码>a、b、c、d、e、f、g,其中每一个都是一个特定的字符串或整数,当在集合中迭代时,它们总是以相同的顺序出现。(不过,不一定是我刚才列出的顺序)

编辑:根据评论进行编辑,以清晰明了

编辑:控制台校对

在Debian 32位上运行python 2.5,在64位上运行python 3,在Windows XP 32位上运行python 2.7。。它们的结果都是一样的,我以前在程序中使用过这个事实,没有任何问题

感谢Chris提供了额外的平台来确认测试

>>> test = ['cat', 'dog', 'mouse', 'rat', 6126, 516]
>>> temp = []
>>> for x in set(test):
    temp.append(x)  
>>> temp
[516, 'dog', 6126, 'cat', 'rat', 'mouse']
>>> temp = []
>>> for x in set(test):
        temp.append(x)
>>> temp
[516, 'dog', 6126, 'cat', 'rat', 'mouse']
>>> 

好的,
\uuu hash\uuu()
的结果应该始终是该对象的唯一结果。对于整数,散列就是值本身

根据:

对象。散列(self)

由内置函数hash()调用,用于对哈希集合(包括set、frozenset和dict)的成员执行操作。hash()应返回整数。唯一需要的属性是比较相等的对象具有相同的哈希值;建议以某种方式将对象组件的哈希值混合在一起(例如,使用异或),这些组件也在对象的比较中发挥作用

因此,对象的顺序将始终取决于该对象的哈希方法的特定实现,并且它是否返回用于比较的“有意义”的内容完全由您在自定义对象上确定


TL;DR-是的,散列将确定对象的顺序。顺序当然取决于散列或这些对象所给出的结果。

< P>作为不保存排序的证明,请考虑DKGasser的例子。在CPython中运行时,结果如下:

>>> test = ['cat', 'dog', 'mouse', 'rat', 6126, 516]
>>> temp = []
>>> for x in set(test):
        temp.append(x)  
>>> temp
[516, 'dog', 6126, 'cat', 'rat', 'mouse']
>>> test = ['cat', 'dog', 'mouse', 'rat', 6126, 516]
>>> temp = []
>>> for x in set(test):
        temp.append(x)  
>>> temp
[6126, 'dog', 'cat', 'rat', 516, 'mouse']
在Jython中运行时,结果如下:

>>> test = ['cat', 'dog', 'mouse', 'rat', 6126, 516]
>>> temp = []
>>> for x in set(test):
        temp.append(x)  
>>> temp
[516, 'dog', 6126, 'cat', 'rat', 'mouse']
>>> test = ['cat', 'dog', 'mouse', 'rat', 6126, 516]
>>> temp = []
>>> for x in set(test):
        temp.append(x)  
>>> temp
[6126, 'dog', 'cat', 'rat', 516, 'mouse']
Q.E.D

它完全依赖于解释器的实现,而完全不受语言本身的保证

编辑

很抱歉把这件事搞砸了,但OP似乎想得到“直接从马嘴里”的确切证据,证明订购无法保证。我终于找到了:

CPython实现细节:键和值以任意顺序列出,这是非随机的,在Python实现中有所不同,并且取决于字典的插入和删除历史记录


好了。请让我们现在就完成这项工作。

从散列集的一般概念来看,您不能依赖顺序。即使您正在使用的实现恰好保持了顺序,但依赖它也不是一个好主意,除非文档明确说明您可以这样做。

所有放入集合的对象的哈希值都保证始终相同,这一事实与集合实现是否保持顺序无关

对于一个简单的散列实现,一个常见的简单方法是创建一个大小为原始大小的数组。插入项目时,会生成其哈希值,然后将其映射(为简单起见,通过mod)到数组大小的值范围,然后将对象放置在数组中的该位置。如果该点已经有一个项目(即数组小于可能的项目数),则使用一些冲突算法

当集合实现中的项数改变时,底层实现可能会改变存储数据的数组的大小(例如,更改为原始大小*1.5)。当这种情况发生时,迭代项的顺序很可能会改变。这通常只发生在插入操作中,但也可能发生在删除操作中,或者即使实现将此类活动分散到其他操作中

有许多不同语言的set实现可以保证顺序,还有一些可以保证插入项目的顺序相同,并且当您插入同一项目两次时,顺序会发生什么变化(例如,它是否移动到末尾,等等)。但是,除非您正在查看的实现明确表示它保证了这一点,否则您不能依赖它


作为一个特定的例子,想象一下,在Python的下一个版本中,确定集合的底层代码是低效的。有人决定重写它以使其更快。即使旧的实现碰巧保持了秩序。。。如果文档没有说明,那么新的实现就可以不使用该属性。

字符串和整数的哈希值绝对没有标准化。它们可以随着Python的任何新实现而改变,包括在2.6.1和2.6.2之间,或者在相同版本的Mac和PC实现之间,等等

但更重要的是,稳定的散列值