add vs update in set operations in python

aceminer picture aceminer · Mar 4, 2015 · Viewed 73.5k times · Source

What is the difference between add and update operations in python if i just want to add a single value to the set.

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

Can someone explain why is this so.

Answer

thefourtheye picture thefourtheye · Mar 4, 2015

set.add

set.add adds an individual element to the set. So,

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

works, but it cannot work with an iterable, unless it is hashable. That is the reason why a.add([1, 2]) fails.

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

Here, [1, 2] is treated as the element being added to the set and as the error message says, a list cannot be hashed but all the elements of a set are expected to be hashables. Quoting the documentation,

Return a new set or frozenset object whose elements are taken from iterable. The elements of a set must be hashable.

set.update

In case of set.update, you can pass multiple iterables to it and it will iterate all iterables and will include the individual elements in the set. Remember: It can accept only iterables. That is why you are getting an error when you try to update it with 1

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

But, the following would work because the list [1] is iterated and the elements of the list are added to the set.

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

set.update is basically an equivalent of in-place set union operation. Consider the following cases

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

Here, we explicitly convert all the iterables to sets and then we find the union. There are multiple intermediate sets and unions. In this case, set.update serves as a good helper function. Since it accepts any iterable, you can simply do

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