我知道python集的元素没有排序。调用pop方法返回一个任意元素;我很好。
我想知道当集合具有相同的历史记录时,pop是否总是会返回相同的元素。当然,在python的一个版本中,我不介意python的不同版本/实现是否有自己的功能。特别是,我问的是python 2.7。在这种情况下,这不仅仅是api的实现问题。
我在游戏的程序性地下城生成器中使用了很多集合,我希望结果对于给定的种子具有确定性。
答案 0 :(得分:24)
答案一般是 no。 @Christophe和@Marcin(联合国)帮助指向的python源显示元素按照它们在哈希表中出现的顺序弹出。因此,弹出顺序(可能是迭代顺序)是确定性的,但仅适用于固定的哈希值。 根据{{3}}文档中的注意,数字的情况就是情况,但不是,这也恰好直接触及了你的问题:
默认情况下,str,bytes和datetime对象的哈希()值被“加盐”,并带有不可预测的随机值。尽管它们在单个Python进程中保持不变,但在重复调用Python之间无法预测它们。
[...]
更改散列值会影响dicts,集和其他映射的迭代顺序。 Python从未对这种排序做出保证(通常在32位和64位版本之间有所不同)。
编辑:正如@Marcin指出的那样,我引用的链接不适用于Python 2。
散列随机化__hash__
默认情况下,Python 2.7没有故意的非确定性字符串散列。
通常,对于其散列不是其值的可重复函数的任何对象(例如,如果散列基于存储器地址),这是一个问题。但相反,如果您为集合中的对象定义自己的__hash__
方法,则可以预期它们将以可重现的顺序返回。 (假设集合的历史和平台保持固定)。
答案 1 :(得分:6)
在内部,我认为情况类似于dict
。该顺序由散列算法确定,在某些情况下将产生相同的结果。但是你不应该依赖它,因为一旦元素的数量变大,该集合将遇到冲突(即它的内部散列),最终导致不同的排序。
简而言之:不,set.pop()
不具有确定性。不要假设任何订单,因为API明确说明了
设置对象是无序集合
答案 2 :(得分:4)
The documentation没有指明它必须是确定性的,因此你应该假设它不是。
答案 3 :(得分:1)
如果你想强迫决定论,你可以尝试像
这样的东西value = min(my_set)
my_set.remove(value)
答案 4 :(得分:-1)
如果您真的针对某个特定版本的python,那么您可以查看源代码并测试其行为(但测试得好 - 考虑负载因素等)。
如果你想要可移植性,或者你发现set
没有按要求执行,请使用ordereddict(这里是一个:http://code.activestate.com/recipes/576693/;还有很多其他的,所以找一个你喜欢的外观),并将其作为一组进行调整。
更新:这是一个有序集:http://packages.python.org/Brownie/api/datastructures.html#brownie.datastructures.OrderedSet