Python Set.pop()不是';不是随机的吗?

Python Set.pop()不是';不是随机的吗?,python,random,Python,Random,从“set.pop()删除并返回s中的任意元素”。在生成一些随机数据来测试程序时,我注意到这个pop()函数的奇怪行为。下面是我的代码(python 2.7.3): 我在这里做的是 在集合s中插入一些随机值,其中每个元素都在范围[0,numberRange) 从集合中弹出一个元素(根据文档,应该是随机的) 计算集合中有多少元素小于弹出值 我希望弹出的值应该是一个随机值,集合中大约50%的数字将大于弹出的值几乎总是返回集合中的最低数字。以下是numberRange=500的结果。第一行表示弹出元素

从“set.pop()删除并返回s中的任意元素”。在生成一些随机数据来测试程序时,我注意到这个pop()函数的奇怪行为。下面是我的代码(python 2.7.3):

我在这里做的是

  • 在集合
    s
    中插入一些随机值,其中每个元素都在范围[0,
    numberRange
  • 从集合中弹出一个元素(根据文档,应该是随机的)
  • 计算集合中有多少元素小于弹出值
  • 我希望弹出的值应该是一个随机值,集合中大约50%的数字将大于弹出的值几乎总是返回集合中的最低数字。以下是
    numberRange=500
    的结果。第一行表示弹出元素的值。第二行是小于弹出值的元素百分比

    9   0   3   1   409     0   1   2   4   0   
    0 % 0 % 0 % 0 % 87 %    0 % 0 % 0 % 0 % 0 %
    
    我使用不同的
    numberRange
    值进行了此测试。似乎对于集合元素的较低值,
    pop()
    几乎总是返回最低的元素。但是对于较高的值,它返回一个随机元素。对于
    numberRange=1000
    ,结果是:

    518     3586    3594    4103    2560    3087    4095    3079    3076    1622    
    7 %     72 %    73 %    84 %    54 %    51 %    79 %    63 %    67 %    32 %
    
    我觉得这很随机。为什么会有这种奇怪的行为?我做错什么了吗

    编辑:感谢大家的回答和评论,似乎“任意”并不保证它是“随机的”。

    当医生说:

    从s中删除并返回任意元素;如果为空,则引发KeyError

    这意味着行为没有定义,实现可以做任何可能的事情。在这种情况下,实现的行为似乎是删除最小的值。仅此而已。
    事实上,
    set.pop()
    基于
    HashMap
    ,并删除其中的第一个元素(较小的hashcode)。对于int的
    set
    ,它是最小的
    int


    Python的其他实现可能会返回一个随机值或第一次推送的值…您不知道。

    这是一个实现细节-
    set
    被实现为一个HashMap(类似于
    dict
    ,但没有一个值槽),
    set.pop
    删除HashMap中的第一个条目,并且
    int
    s哈希值是相同的int


    结合起来,这意味着您的
    集合
    (按散列值排序)实际上也按以散列表大小为模的条目排序;在您的情况下,这应该接近自然排序,因为您只插入一个小范围内的数字-如果您从
    随机范围(10**10)中获取随机数
    而不是
    randrange(500)
    您应该看到不同的行为。此外,根据您的插入顺序,由于散列冲突,您可以从原始散列顺序中获取一些值。

    它不是随机的,而是无序的。文档的“任意”并不意味着“随机”“不要依赖于任何特定的值,实现细节可能会在没有警告的情况下更改”Random并不意味着它分布得很好,甚至不可预测。它意味着你不能依赖任何观察结果在将来是真实的。是的,我想这是多么糟糕的
    Random。选择
    对集合不起作用。此外,
    random.choice
    对dicts来说是完全错误的。@wim:同意,如果有人刚刚阅读了
    random
    文档,不理解Python/C++行话“序列“,
    集合
    dict
    不是一个集合并不明显。我对“序列”、“iterable”、“迭代器”这样的术语没有强烈的感觉”在Python文档的各个部分中都假定有词汇表,但毫无疑问,它至少吸引了大多数人一次。另外,如果
    random.choice
    处理任意iterable(在
    O(n)
    time和
    O(1)
    memory中)会更好在集合和DICT上,无论时间复杂度如何都是可行的。这是由于将
    set
    作为HashMap实现而导致的实现细节,intsYour第二段的哈希值是不正确的。只有当插入的值相对于集合大小很小时,才是正确的。所有赌注都将以较大的值结束。@interjay是的,你是没错,编辑atm——它当然是按哈希表大小的模排序的;但由于OP是从一个小范围插入数字,所以对他的情况来说应该是正确的。
    518     3586    3594    4103    2560    3087    4095    3079    3076    1622    
    7 %     72 %    73 %    84 %    54 %    51 %    79 %    63 %    67 %    32 %