Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/image-processing/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python—使用set.add()时添加元素的位置_Python_Set_Element_Add - Fatal编程技术网

Python—使用set.add()时添加元素的位置

Python—使用set.add()时添加元素的位置,python,set,element,add,Python,Set,Element,Add,我发现,当我使用python的set结构的add函数时,元素似乎被添加到了我无法理解的位置 >>> a=set([(0, 2)]) >>> a.add((0,4)) >>> a set([(0, 2), (0, 4)]) >>> a.add((1,0)) >>> a set([(1, 0), (0, 2), (0, 4)]) >>> a.add((2,5)) >>> a

我发现,当我使用python的set结构的add函数时,元素似乎被添加到了我无法理解的位置

>>> a=set([(0, 2)])
>>> a.add((0,4))
>>> a
set([(0, 2), (0, 4)])
>>> a.add((1,0))
>>> a
set([(1, 0), (0, 2), (0, 4)])
>>> a.add((2,5))
>>> a
set([(2, 5), (1, 0), (0, 2), (0, 4)])
>>> a.add((3,0))
>>> a
set([(3, 0), (2, 5), (1, 0), (0, 2), (0, 4)])
>>> a.add((1,6))
>>> a
set([(3, 0), (0, 2), (1, 6), (0, 4), (2, 5), (1, 0)])

正如可以看到的,有时元素在开始和其他时间,在结尾或中间添加。在上一个示例中,现有元素也被重新排序


知道插入是如何发生的吗?

集合是无序的。元素在集合中的“where”的概念是未定义的。

python中的集合是无序的。顺序是任意的。

集合使用与dict相同的哈希函数来添加元素。事实上,它们只是没有值元素的dict

也许能帮助你更好地理解它

如果使用整数,集合将按顺序排列(按“人类”的排序方式排列):

但如果使用元组,它们对人眼来说不是“有序的”:

>>> s=set()
>>> for t in ((i,i*i) for i in range(10)):
...    s.add(t)
...    print s
... 
set([(0, 0)])
set([(0, 0), (1, 1)])
set([(0, 0), (1, 1), (2, 4)])
set([(3, 9), (0, 0), (1, 1), (2, 4)])
set([(3, 9), (0, 0), (1, 1), (4, 16), (2, 4)])
set([(0, 0), (4, 16), (5, 25), (3, 9), (2, 4), (1, 1)])
set([(6, 36), (0, 0), (4, 16), (5, 25), (3, 9), (2, 4), (1, 1)])
set([(6, 36), (0, 0), (7, 49), (4, 16), (5, 25), (3, 9), (2, 4), (1, 1)])
set([(6, 36), (0, 0), (7, 49), (4, 16), (5, 25), (3, 9), (2, 4), (1, 1), (8, 64)])
set([(6, 36), (0, 0), (7, 49), (4, 16), (5, 25), (3, 9), (9, 81), (2, 4), (1, 1), (8, 64)])
现在在解释器中尝试以下两行:

>>> dict.fromkeys(range(10),None)
{0: None, 1: None, 2: None, 3: None, 4: None, 5: None, 6: None, 7: None, 8: None, 9: None}
>>> dict.fromkeys(((i,i*i) for i in range(10)),None)
{(6, 36): None, (0, 0): None, (7, 49): None, (4, 16): None, (5, 25): None, (3, 9): None, (9, 81): None, (2, 4): None, (1, 1): None, (8, 64): None}
您可以看到生成的dict与设置示例的“顺序”相同

虽然只有int键的dict和set可能是“有序的”,但从实用的角度来看,dict和set没有顺序。


如果您观看链接的视频,您将了解原因。

元素根据其哈希值转到哈希表中的特定位置。对于最后3位相同的元素,会发生冲突,并为其选择其他点。哈希表在满2/3时立即展开,以降低冲突率。 在哈希表上看到这个

>>> def bits(n):
    n+=2**32
    return bin(n)[-32:]

>>> bits(hash('a'))
'11100100000011011011000111100000' #last three bits are picked to determine the spot in hash table
>>> bits(hash('b'))
'11101011101011101101001101100011'

正如其他答案所说:

  • 布景应该表现得像没有秩序一样
  • 向集合添加内容的实际机制与字典相同;集合基本上是没有项的键的字典
  • 字典基于哈希表(有关此方面的详细信息:)
我认为了解幕后发生的事情可能会有用,所以我对set的
add()
方法的实际源代码进行了注释(很抱歉滚动)


正如您所看到的,set
add(element)
与dict
add(element)
是相同的,只是它更难对
元素进行散列

不是随机的。元素是散列的,集合是建立在基于这些散列“显然是随机的”或与你看不见的东西相关的散列表上的。当你因为别人的评论而修改你的答案时,你会怎么做?保持原样是正确的吗?@thikonom提到这篇文章是经过编辑的,如果有人修改了你的答案,而你同意,那么编辑是公平的!这是必须的手表。
>>> def bits(n):
    n+=2**32
    return bin(n)[-32:]

>>> bits(hash('a'))
'11100100000011011011000111100000' #last three bits are picked to determine the spot in hash table
>>> bits(hash('b'))
'11101011101011101101001101100011'
def add(self, element):
    """Add an element to a set.

    This has no effect if the element is already present.
    """
    try:
        self._data[element] = True                             # self._data is the dictionary where all of the set elements are stored
    except TypeError:                                          # this try...except block catches the cases when element cannot be a dict key (that is, it isn't hashable)
        transform = getattr(element, "__as_immutable__", None) # the getattr() call is the same as trying to get element.__as_immutable__ and returning None if element doesn't have __as_immutable__
        if transform is None:                                     
            raise # re-raise the TypeError exception we caught # if we get to this line, then the element has no defined way to make it immutable (and thus hashable), so a TypeError is raised
        self._data[transform()] = True                         # so if we get here, transform() is the same as calling element.__as_immutable__() (which we know exists), and we can now add it to the self._data dict