在Python的集合操作中,add和update有什么区别?

95

如果我只想向集合中添加一个单独的值,在Python中添加和更新操作有什么区别?

a = set()
a.update([1]) #works
a.add(1) #works
a.update([1,2])#works
a.add([1,2])#fails 

有人能解释一下为什么会这样吗?


1
你使用的是哪个版本的Python?对于a.update(1),我期望得到TypeError:'int' object is not iterable错误信息,并在我尝试的两个版本中都得到了这个错误。 - Steve Jessop
1
@thefoutheye,您的编辑相当大地改变了问题。 - Padraic Cunningham
@PadraicCunningham OP提到了#fails#works。我只是包含了实际的错误信息。希望这样可以。 - thefourtheye
1
@PadraicCunningham 我们都知道这不会起作用。我们能否一致同意这只是一个复制/粘贴错误?如果不能,请随时撤销我的修改 :) - thefourtheye
1
@thefoureye 是的,这是我自己复制粘贴时出错了。 - aceminer
显示剩余8条评论
9个回答

114

set.add

set.add 将一个独立的元素添加到集合中。因此,

>>> a = set()
>>> a.add(1)
>>> a
set([1])

这个函数可以工作,但是如果它的参数是一个可迭代对象且不可哈希时,它就无法正常工作。这就是为什么a.add([1, 2])会失败的原因。

>>> a.add([1, 2])
Traceback (most recent call last):
  File "<input>", line 1, in <module>
TypeError: unhashable type: 'list'

在这里,[1, 2]被视为要添加到集合中的元素。正如错误信息所说,列表不能被哈希,但是集合中的所有元素都必须是可哈希的,引用文档

返回一个由可迭代对象中的元素组成的新的setfrozenset对象。集合的元素必须是可哈希的

set.update

在使用set.update时,可以向其传递多个可迭代对象,它将迭代所有可迭代对象并将其中的单个元素包含在集合中。请记住:它只能接受可迭代对象。这就是为什么当您尝试使用1更新它时会出现错误的原因。

>>> a.update(1)
Traceback (most recent call last):
  File "<input>", line 1, in <module>
TypeError: 'int' object is not iterable

但是,下面的代码可以工作,因为对列表 [1] 进行了迭代,并将列表元素添加到集合中。

>>> a.update([1])
>>> a
set([1])

set.update基本上是就地修改(set union)操作的等效形式。考虑以下情况:

>>> set([1, 2]) | set([3, 4]) | set([1, 3])
set([1, 2, 3, 4])
>>> set([1, 2]) | set(range(3, 5)) | set(i for i in range(1, 5) if i % 2 == 1)
set([1, 2, 3, 4])

在这里,我们明确将所有可迭代对象转换为集合,然后找到它们的并集。这里涉及多个中间集合和联合操作。在这种情况下,set.update 函数是一个很好的辅助函数。由于它接受任何可迭代对象,所以你可以简单地执行以下操作:

>>> a.update([1, 2], range(3, 5), (i for i in range(1, 5) if i % 2 == 1))
>>> a
set([1, 2, 3, 4])

如果您想从可迭代的可迭代对象中更新my_set集合,则必须使用my_set.update(*[s for s in iterable]),并像这样传递一个生成器my_set.update(s for s in iterable),将使用可迭代对象的元素更新集合,并且如果这些元素不可哈希,则会出现错误。 - Mr_and_Mrs_D

27

add对于单个元素来说更快,因为它的目的正是添加单个元素:

In [5]: timeit a.update([1])
10000000 loops, best of 3: 191 ns per loop

In [6]: timeit a.add(1) 
10000000 loops, best of 3: 69.9 ns per loop

update 需要一个可迭代对象或多个可迭代对象作为参数,如果你只有一个可哈希元素需要添加,则使用 add;如果你有多个可哈希元素需要添加,则使用 update

s.add(x) 向集合 s 添加元素 x

s.update(t) 等价于 s |= t,返回将 t 中的元素添加到 s 后得到的集合 s


6
虽然这可能很显然,但需要注意的是,update对于一次性添加大量元素要快得多:timeit a.update(range(10000)) # => 1000 loops, best of 3: 431 µs per loop,而同时,timeit for i in range(10000): a.add(i) # => 1000 loops, best of 3: 1.18 ms per loop - Matt Hancock

12

add 方法可以添加一个元素至集合中,update 方法则可以一次性地添加多个元素到集合中,这些元素可以来自于另一个集合(set)或者列表(list)。

In [2]: my_set = {1,2,3}

In [3]: my_set.add(5)

In [4]: my_set
Out[4]: set([1, 2, 3, 5])

In [5]: my_set.update({6,7})

In [6]: my_set
Out[6]: set([1, 2, 3, 5, 6, 7])

请注意,这种符号表示法相对较新。根据https://dev59.com/Bm025IYBdhLWcg3wPzbL#31072911,它适用于Python 2.7和Python 3.1。 - Evgeni Sergeev

5

.add()是用于单个元素的,而.update()用于引入其他集合。

来自help():

add(...)
    Add an element to a set.

    This has no effect if the element is already present.


update(...)
    Update a set with the union of itself and others.

3

add 只接受可哈希的类型。列表不是可哈希的。


3

a.update(1) 在您的代码中不起作用。 add 接受一个元素并将其放入集合中(如果它还不存在),但是update接受一个可迭代对象,并使用该可迭代对象创建一个集合的联合。这有点像列表的appendextend


1

我想没有人提到过Hackerrank上的好资源。我想粘贴一下Hackerrank是如何在Python中说明set的update和add之间的区别的。

集合是无序的唯一值的袋子。单个集合包含任何不可变数据类型的值。

创建集合

myset = {1, 2} # Directly assigning values to a set

myset = set() # Initializing a set

myset = set(['a', 'b']) # Creating a set from a list

print(myset)  ===> {'a', 'b'}

修改集合 - add() 和 update()
myset.add('c')

myset  ===>{'a', 'c', 'b'}

myset.add('a') # As 'a' already exists in the set, nothing happens

myset.add((5, 4))

print(myset) ===> {'a', 'c', 'b', (5, 4)} 


myset.update([1, 2, 3, 4]) # update() only works for iterable objects

print(myset) ===> {'a', 1, 'c', 'b', 4, 2, (5, 4), 3}

myset.update({1, 7, 8})

print(myset) ===>{'a', 1, 'c', 'b', 4, 7, 8, 2, (5, 4), 3}

myset.update({1, 6}, [5, 13])

print(myset) ===> {'a', 1, 'c', 'b', 4, 5, 6, 7, 8, 2, (5, 4), 13, 3}

希望能对您有所帮助。如果需要更多有关Hackerrank的详细信息,这里是链接。


0

我们使用add()方法向集合中添加单个值。

我们使用update()方法向集合中添加序列值。

这里的序列可以是任何可迭代对象,包括listtuplestringdict等。


1
关于已有的答案,实际上并没有任何额外的价值。 - colidyre

0

add方法直接将元素添加到集合中,而update方法会将第一个参数转换为集合,然后再进行添加操作。由于列表是可哈希的,因此我们不能将可哈希的列表添加到不可哈希的集合中。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接