我知道python set的元素是无序的。调用pop方法会返回任意一个元素;这一点我没问题。
我想知道的是,在同样的历史记录下,pop是否总是返回相同的元素。当然,我不介意不同版本/实现的Python做出自己的事情。特别是,我询问的是Python 2.7。在这种情况下,这更多是一种实现方式而不是API的问题。
我在一个过程化地图生成器中经常使用set,并且希望给定种子时结果是确定性的。
__hash__
文档中的Note,对于字符串则不是这样, 顺带一提直接涉及到了你的问题:
编辑:正如@Marcin所指出的,我引用的链接不适用于Python 2。哈希随机化成为Python 3.3的默认设置。 Python 2.7默认情况下没有不确定性的字符串哈希。请注意,默认情况下,str、bytes 和 datetime 对象的 hash() 值会“撒盐”,并加上一个不可预测的随机值。虽然在单个 Python 进程内它们保持不变,但在重复调用 Python 时它们是不可预测的。
[...]
更改哈希值会影响字典、集合和其他映射的迭代顺序。Python从来没有对此排序作出过任何保证(通常在32位和64位版本之间有所不同)。
__hash__
方法,则可以期望它们以可重复的顺序返回。(前提是集合的历史和平台保持不变)。dict
。顺序由哈希算法确定,在某些情况下,将产生相同的结果。但是您不应该依赖于此,因为一旦元素数量变大,集合将遇到冲突(即它的内部哈希),这最终会导致不同的排序。
简而言之:不,set.pop()
不是确定性的。不要假设任何顺序,因为API明确说明:
一个集合对象是一个无序的集合
文档没有指定必须是确定的,因此您应该假设它不是。
value = min(my_set)
my_set.remove(value)
__lt__
使得 x < y
和 y < x
同时成立,虽然是合法的写法,但实际上是错误的。 - Karl Knechtelclass epsilon(float): def __lt__(self, other): return True if 0 < other
- ch3ka如果你真的是针对特定版本的Python,那么你可以查看源代码,并测试其行为(但要进行充分的测试-考虑负载因素等)。
如果您想要可移植性,或者发现set
的执行不符合要求,请使用有序字典(这里有一个:http://code.activestate.com/recipes/576693/;还有很多其他的,找到一个你喜欢的),并将其适应为一个集合。
更新:这里有一个有序集合:http://packages.python.org/Brownie/api/datastructures.html#brownie.datastructures.OrderedSet
set.pop()
以及list(set())
可以是确定性的。 - Joel Cornettset.pop()
时假设非确定性。如果你想知道从集合中删除元素的确定性方法,那么请提出另一个问题。这个问题已经有答案了。 - Mike Williamson