Python 3.41 A set
我有两个关于布景的问题。
1。所以当我读到集是无序的,但当我开始试验它们时,我发现实际上有某种排序的东西。
正如您所看到的,这个集合中没有什么特别的:
1 2 3 | >>> v_set ={88,11,1,33,21,3,7,55,37,8} >>> v_set {33, 1, 3, 37, 7, 8, 11, 21, 55, 88} |
但这个不同:
1 2 3 | >>> g_set={7,5,11,1,4,13,55,12,2,3,6,20,9,10} >>> g_set {1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 12, 13, 20, 55} |
号
我想,这是因为这次我写下了更多更接近的数字,并且开始有意义地设置这些数字的升序…?
2。第二个问题是关于pop()。我读到没有办法控制用pop()方法删除哪个值,它是完全任意的。打赌,当我使用pop()方法时,它总是(我从来没有看到不同的情况)从左侧集合获取第一个项目。
如你所见:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | >>> v_set {33, 1, 3, 37, 7, 8, 11, 21, 55, 88} >>> v_set.pop() 33 >>> v_set.pop() 1 >>> v_set.pop() 3 >>> v_set.pop() 37 >>> v_set.pop() 7 >>> v_set.pop() 8 >>> v_set.pop() 11 >>> v_set.pop() 21 >>> v_set.pop() 55 |
那么它真的是完全武断的吗?
注意元素的顺序也取决于插入的顺序。当发生碰撞时,您很容易看到:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | In [4]: class Bad: ...: def __init__(self, val, hash_val): ...: self.val = val ...: self.hash_val = hash_val ...: def __str__(self): ...: return 'Bad({0.val}, {0.hash_val})'.format(self) ...: __repr__ = __str__ ...: def __eq__(self, other): ...: return self.val == other.val ...: def __hash__(self): ...: return self.hash_val In [5]: b1 = Bad(1, 1) ...: b2 = Bad(2, 1) ...: b3 = Bad(3, 2) In [6]: {b1, b2, b3} Out[6]: {Bad(2, 1), Bad(3, 2), Bad(1, 1)} In [7]: {b2, b1, b3} Out[7]: {Bad(1, 1), Bad(3, 2), Bad(2, 1)} |
在
如果没有碰撞:
1 2 3 4 5 6 7 8 9 | In [8]: b1 = Bad(1, 1) ...: b2 = Bad(2, 2) ...: b3 = Bad(3, 3) In [9]: {b1, b2, b3} Out[9]: {Bad(1, 1), Bad(2, 2), Bad(3, 3)} In [10]: {b2, b1, b3} Out[10]: {Bad(1, 1), Bad(2, 2), Bad(3, 3)} |
号
注意订单没有改变。(好吧,散列使用的是一些
换句话说,这些值不足以确定
一般来说,
他们可以真正随机化输出,但这只会增加开销,没有任何好处。
它不是完全武断的。但这并不重要。
我们称集合为无序的,因为作为该代码的用户或客户端,您不能依赖于特定的顺序。但是,根据集合实现的详细信息,可能有一些顺序。
与
总之,文档为您提供了一组保证,任何兼容的Python实现都将遵循这些保证。您观察到的其他影响是实现细节,可能随时发生变化。
是的,根据定义,排序是任意的。即使项目按排序顺序存储,它仍然是任意的。""任意"意味着Python不承诺以任何特定的方式订购数据。因为内存是线性的,所以它必须使用某种顺序,但是您永远不应该依赖于这种顺序,因为它可能会在未经通知的情况下被更改。(实际上,在最新版本的python中,
第二个示例显示打印顺序与弹出顺序相同。这是有道理的:
如果您想知道这是如何工作的,请阅读哈希表。