Python 3.41 一套 [英] Python 3.41 A set

查看:50
本文介绍了Python 3.41 一套的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个关于集合的问题.

1.所以当我读到集合是无序的,但是当我开始尝试它们时,我发现实际上有某种排序的东西.

正如你所看到的,这个集合没有什么特别的:

<预><代码>>>>v_set ={88,11,1,33,21,3,7,55,37,8}>>>v_set{33, 1, 3, 37, 7, 8, 11, 21, 55, 88}

但是这个不一样:

<预><代码>>>>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() 方法时,它总是(我从来没有看到过不同)从左侧开始获取集合中的第一项.

如您所见:

<预><代码>>>>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

那么它真的是完全随意的吗?

解决方案

请注意,元素的顺序(也)取决于插入的顺序.当发生碰撞时,您可以很容易地看到这一点:

在 [4]: class Bad:...: def __init__(self, val, hash_val):...: self.val = val...: self.hash_val = hash_val...: def __str__(self):...:返回 'Bad({0.val}, {0.hash_val})'.format(self)...: __repr__ = __str__...: def __eq__(self, other):...:返回 self.val == other.val...: def __hash__(self):...:返回 self.hash_val在 [5] 中:b1 = Bad(1, 1)...: b2 = 坏(2, 1)...: b3 = 坏(3, 2)在 [6] 中:{b1, b2, b3}输出[6]:{坏(2, 1),坏(3, 2),坏(1, 1)}在 [7] 中:{b2, b1, b3}输出[7]:{坏(1, 1),坏(3, 2),坏(2, 1)}

正如您在 Out[6] 中看到的,第一个元素是 Bad(2, 1),最后一个元素是 Bad(1, 1) 而在 Out[7] 中,第一个是 Bad(1, 1),最后一个是 Bad(2, 1).

如果没有碰撞:

在[8]中:b1 = Bad(1, 1)...: b2 = 坏(2, 2)...: b3 = 坏(3, 3)在 [9] 中:{b1, b2, b3}输出[9]:{坏(1, 1),坏(2, 2),坏(3, 3)}在 [10] 中:{b2, b1, b3}输出[10]:{坏(1, 1),坏(2, 2),坏(3, 3)}

注意顺序没有改变.(好吧,散列用于对一些 n 进行模数,因此即使散列不同,也可能存在冲突,具体取决于基础表的大小.

换句话说这些值不足以确定set元素的顺序,即使您知道它们是如何实现的.您还必须知道插入的顺序.

一般来说,sets do 有一个明确定义的顺序inside 单个解释器运行(由于 python3.3+ 中的随机化),但是使用哪个顺序取决于执行的插入(值和它们完成的顺序),并且是任意,即在python3.5中它们可以更改订单恕不另行通知,因此您不能依赖它.

他们可以真正地随机化输出,但这只会增加开销而没有任何好处.

I have two questions about sets.

1. So as I read sets are unordered, but when I started experimenting with them I found out that actually there is some kind of ordering thing.

As you can see, there is nothing special in this set:

>>> v_set ={88,11,1,33,21,3,7,55,37,8}
>>> v_set
{33, 1, 3, 37, 7, 8, 11, 21, 55, 88}

But this one is different:

>>> 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}

I guess, it's because this time I wrote down more closer numbers, and it started to make sense to set those numbers ascending sequence...?

2. And the second question is about pop(). I read that there is no way to control which value gets removed with pop() method, it is completely arbitrary. Bet when I use pop() method it always (I never saw differently) takes the first item from the left side in sets.

As you can see:

>>> 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

So is it really completely arbitrary?

解决方案

Note that the order of the elements depends (also) on the order of the insertions. You can easily see this when there are collisions:

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)}

As you can see in Out[6] the first element is Bad(2, 1) and the last is Bad(1, 1) while in Out[7] the first is Bad(1, 1) and the last is Bad(2, 1).

If there were no collisions:

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)}

note how the order didn't change. (Well, the hash is used modulus some n so there can be collisions even if the hashes are different, depending on the size of the underlying table).

In other words the values aren't enough to determine the order of the elements of a set, even if you know how they are implemented. You must also know the order of the insertions.

In general sets do have a well defined order inside a single interpreter run (due to randominzation in python3.3+), however which order is used is depends on the insertions performed (both the value and the order in which they are done), and is arbitrary, i.e. in python3.5 they can change the order without notice, so you cannot rely on it.

They could truly randomize the outputs but this would simply add overhead for no benefit.

这篇关于Python 3.41 一套的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆