# Python Sets

Set is a collection of items. Apart from sets, three other data types used as collection of data are List, Tuple and Dictionary. We have already learnt about the other three and will go through sets in this chapter.

## Why Sets?

Just like lists, tuples and dictionaries, sets are also used to store data. So, why a new data type? What makes sets different from lists and tuples is that a set can’t store duplicate data. For example, a list can have an element more than once, whereas a set can have an element only once.

A set in Python is similar to the set about which we talk in our day-to-day life. For example, a set of books, a set of movies, a set of students. We know that a set of students can’t have a student more than once. Thus, a set of students consists of the names of unique students. Similarly, a set of movies consists of the names of unique movies.

Therefore, sets are used when we want to store unique data.

## Creating a Python Set

The items/elements in a set are enclosed within braces { } and separated by commas. The elements can be of the same or different data types.

myset = {1, 2, 3}
print(myset)

{1, 2, 3}

In the above example, myset is a set having three elements of type integer.

myset = {1, 2, 3, "Hello"}
print(myset)

{1, 2, 3, 'Hello'}

In the above example, myset is a set having elements of different data types.

An empty set is defined using the set() function as shown below.

myset = set()
print(myset)

set()
We can’t use { } to create an empty set because it creates an empty dictionary.

## Properties of Python Set

### Each element in a set is unique

There can’t be duplicates of any element present in a set.

myset = {1, 2, 3, 2}
print(myset)

{1, 2, 3}

We assigned the element 2 twice in the set but it got discarded.

### A set is unordered

Elements in a set don’t have a specific order. Their order can get changed every time you use them.

Consider the following code.

myset = {1, 2, 3, "1", "Hello"}
print(myset)


On running it, we got a different result each time. For example, we got the following result on running it the first time.

{1, 2, 3, 'Hello', '1'}

On running the second time, we got the following result.

{'Hello', 1, 2, 3, '1'}

This is also the reason why we can’t access elements of a set through index or position.

The elements of a set can’t be accessed through index or position.

### Elements of a set are immutable

If a data type is immutable, it means that its elements can’t be added or deleted. Examples of immutable data types are int, float, bool, string and tuple. Examples of mutable data types are list, dictionary and set.

Therefore, lists, dictionaries or sets can’t be elements of a set.

The following set is valid.

myset = {1, 2, 3.2, "1", "Hello", (10, 20)}
print(myset)

{1, 2, 3.2, 'Hello', '1', (10, 20)}

The following set is invalid because it contains a list which is mutable.

myset = {1, 2, 3.2, "1", "Hello", [10, 20]}
print(myset)

Traceback (most recent call last):
File "<stdin>", line 2, in <module>
TypeError: unhashable type: 'list'
The elements of a set can’t be changed, but new elements can be added.

### Sets are mutable

The elements of a set can be added or deleted.

## Adding Elements to Python Set

We can add new elements to a set using the following functions.

The add() function adds a single element to a set.

myset = {1, 2, 3}
print(myset)

{1, 2, 3, 5}

myset.add(5) added 5 to the set myset.

### Python update()

The update() function takes lists, strings, tuples and other sets as an argument and adds the elements in the passed arguments to the set.

myset = {1, 2, 3}
myset.update([5, 10])
print(myset)

{1, 2, 3, 5, 10}

In the above example, a list [5, 10] is passed to the update() function. Thus, the elements of the list got appended to the set.

myset = {1, 2, 3}
myset.update([5, 10], [15, 20], {25, 30})
print(myset)

{1, 2, 3, 5, 10, 15, 20, 25, 30}

Here, since two lists and a set are passed to the update() function, their elements got added to the set myset.

## Deleting Elements from Python Set

The discard() function is used to remove a particular element from a set.

colors = {"Blue", "Green", "Red", "Orange", "Yellow", "Brown"}
colors.discard("Green")  # removing "Green" from set
print(colors)

{'Yellow', 'Orange', 'Blue', 'Brown', 'Red'}

colors.discard("Green") removed "Green" from the set colors.

If we try to remove an element which is not present in the set, discard() doesn’t throw an error.

colors = {"Blue", "Green", "Red", "Orange", "Yellow", "Brown"}
print(colors)

{'Green', 'Yellow', 'Red', 'Brown', 'Orange', 'Blue'}

"Violet" is not present in the set, still trying to remove it didn’t throw any error.

### Python remove()

The remove() function is used to remove a particular element from a set. It differs from discard() as it throws the “KeyError” if we try to remove an element which is not present in the set.

colors = {"Blue", "Green", "Red", "Orange", "Yellow", "Brown"}
colors.remove("Green")  # removing "Green" from set
print(colors)

{'Yellow', 'Orange', 'Blue', 'Brown', 'Red'}

colors.remove("Green") removed "Green" from the set.

If we try to remove an element which is not present in the set, remove() throws the “KeyError” as shown below.

colors = {"Blue", "Green", "Red", "Orange", "Yellow", "Brown"}
colors.remove("Violet")

Traceback (most recent call last):   File "<stdin>", line 2, in <module> KeyError: 'Violet'

### Python pop()

For sets, the pop() function behaves differently because we can’t remove an element by index. This function removes an element randomly and returns the removed element.

colors = {"Blue", "Green", "Red", "Orange", "Yellow", "Brown"}
colors.pop()
print(colors)

{'Orange', 'Green', 'Red', 'Brown', 'Blue'}

In the above example, pop() selected a random element and removed it from the set.

### Python clear()

The clear() function removes all the elements from a set.

colors = {"Blue", "Green", "Red", "Orange", "Yellow", "Brown"}
colors.clear()  # removing all element from set
print(colors)

set()

## Python Set Operations

Some mathematical operations like union, intersection, difference and symmetric difference on sets can be implemented on Python sets as well. For that, consider the two sets s1 and s2 on which we will be performing the operations.

s1 = {1, 2, 3, 4, 5, 6}
s2 = {4, 5, 6, 7, 8}


### Python Set Union

Union of sets s1 and s2 is a new set having all the elements of both the sets.

Union can be performed using the | operator.

s1 = {1, 2, 3, 4, 5, 6}
s2 = {4, 5, 6, 7, 8}
print(s1 | s2)

{1, 2, 3, 4, 5, 6, 7, 8}

Union can also be performed using the union() function.

s1 = {1, 2, 3, 4, 5, 6}
s2 = {4, 5, 6, 7, 8}

print(s1.union(s2))
print(s2.union(s1))

{1, 2, 3, 4, 5, 6, 7, 8}
{1, 2, 3, 4, 5, 6, 7, 8}

### Python Set Intersection

Intersection of sets s1 and s2 is a new set having the common elements of both the sets.

Intersection can be performed using the & operator.

s1 = {1, 2, 3, 4, 5, 6}
s2 = {4, 5, 6, 7, 8}

print(s1 & s2)

{4, 5, 6}

4, 5 and 6 are present in both the sets and hence constitutes the intersection set s1 & s2.

Intersection can also be performed using the intersection() function.

s1 = {1, 2, 3, 4, 5, 6}
s2 = {4, 5, 6, 7, 8}

print(s1.intersection(s2))
print(s2.intersection(s1))

{4, 5, 6}
{4, 5, 6}

### Python Set Difference

Difference of set s1 from set s2 is a new set having the elements which are present in s1 and not in s2.

Difference can be performed using the - operator.

s1 = {1, 2, 3, 4, 5, 6}
s2 = {4, 5, 6, 7, 8}

print(s1 - s2)
print(s2 - s1)

{1, 2, 3}
{8, 7}

Set s1 - s2 consists of the elements present in s1 but not in s2, and set s2 - s1 consists of the elements present in s2 but not in s1.

Difference can also be performed using the difference() function.

s1 = {1, 2, 3, 4, 5, 6}
s2 = {4, 5, 6, 7, 8}

print(s1.difference(s2))
print(s2.difference(s1))

{1, 2, 3}
{8, 7}

s1.difference(s2) is equivalent to s1 - s2 and s2.difference(s1) is equivalent to s2 - s1.

### Python Set Symmetric Difference

Symmetric Difference of sets s1 and s2 is a new set having the elements in s1 and s2 but not the common elements in both. It can be seen as (union - intersection).

Difference can be performed using the ^ operator.

s1 = {1, 2, 3, 4, 5, 6}
s2 = {4, 5, 6, 7, 8}

print(s1 ^ s2)

{1, 2, 3, 7, 8}

Symmetric difference can also be performed using the symmetric_difference() function.

s1 = {1, 2, 3, 4, 5, 6}
s2 = {4, 5, 6, 7, 8}

print(s1.symmetric_difference(s2))
print(s2.symmetric_difference(s1))

{1, 2, 3, 7, 8}
{1, 2, 3, 7, 8}

### Python Set Membership Test

We can test if an element is present in a set using the membership operators in and not in.

myset = {1, 2, "Blue", "Green"}
print(2 in myset)
print(4 in myset)
print("Green" not in myset)

True
False
False

## Iteration Through a Python Set

We can iterate through a set using a for loop.

colors = {"Blue", "Green", "Red"}
for color in colors:
print(color)

Blue
Green
Red

A variable color goes to each element in the set colors and takes its value, and that value is printed on the screen.

## Different Ways to Create a Python Set

We already know how to create a set.

An empty set is created as follows.

myset = set()

A set having elements is created as follows.

myset = {1, 2, 3, 4}

Sets can also be created using the set() function. This function converts a sequence (list, string, tuple) or a collection(dictionary, set) into a set.

In the following example, a list, a string and a set are converted to sets.

set1 = set([1, 2, 3])  # list is converted to set
set2 = set("Codesdope")  # string is converted to set
set3 = set((1, 2, 3, 4))  # set is converted to set
print(set1)
print(set2)
print(set3)

{1, 2, 3}
{'o', 'e', 'C', 'p', 's', 'd'}
{1, 2, 3, 4}

## Python Copying Set

Let’s look at the different ways we can copy a set.

### Simple Assignment

A set can be copied to a variable by simply assigning it to the variable.

set1 = {1, 2, 3, 4}
set2 = set1
print(set2)

{1, 2, 3, 4}

Here, the set stored in the variable set1 is assigned to the variable set2. Thus, both the variables store the same set. As a result, if some change is made in set2, it will also get reflected in set1, which is often undesirable.

Let’s see how a change in set2 is getting reflected in set1.

set1 = {1, 2, 3, 4}
set2 = set1
print("Original set:", set1)
print("New set:", set2)

Original set: {1, 2, 3, 4, 10}
New set: {1, 2, 3, 4, 10}

On changing set2, set1 also got changed. This is because both the variables are pointing to the memory location of the same set.

To prevent this, we can use the copy() function.

### Python copy()

copy() is used to create a shallow copy of a set.

set1 = {1, 2, 3, 4}
set2 = set1.copy()
print("Original set:", set1)
print("New set:", set2)

Original set: {1, 2, 3, 4}
New set: {1, 2, 3, 4, 10}

In this example, a shallow copy of set1 is created using copy() and that copy is assigned to set2. As a result, modifying set2 didn’t modify set1 because now the variables are pointing to the memory addresses of different sets.

### Python set()

A set can be copied by passing it to the set() function.

set1 = {1, 2, 3, 4}
set2 = set(set1)
print("Original set:", set1)
print("New set:", set2)

Original set: {1, 2, 3, 4}
New set: {1, 2, 3, 4, 10}

We created a new set having all the elements of set1 using set(set1) and assigned this newly created set to set2.

## Built-in Functions in Python for Set

The functions available in Python which can be used with sets are shown below.

### len()

It returns the number of elements in a set.

myset = {1, 2, 3, 4, 5, 6}
print(len(myset))

6

### max()

It returns the element from a set that has the maximum value.

myset = {3, 2, 1, 5, 6, 4}
print(max(myset))

6

### min()

It returns the element from a set that has the minimum value.

myset = {3, 2, 1, 5, 4}
print(min(myset))

1

### sum()

It returns the sum of all the elements in a set.

myset = {3, 2, 1, 5, 6, 4}
print(sum(myset))

21

### sorted()

It returns a sorted list from the set.

myset = {3, 2, 1, 5, 6, 4}
print(sorted(myset))

[1, 2, 3, 4, 5, 6]

To sort the elements in descending order, pass another argument reverse=True to the sorted() function.

myset = {3, 2, 1, 5, 6, 4}
print(sorted(myset, reverse=True))

[6, 5, 4, 3, 2, 1]

### any()

It returns True if any of the elements in a set are True. Otherwise, it returns False.

myset = {3, 2, 1, True}
print(any(myset))

True

any(mytuple) returned True because all the elements of the set are non-zero or True.

Look at another example where one element of the set is False.

myset = {3, 2, 1, False}
print(any(myset))

True

In the above example, one element of the set is False, but still the any() function returned True. This is because if atleast one element is non-zero or True, then the function returns True.

### all()

It returns True if all the elements in a set are True. Otherwise, it returns False.

myset = {3, 2, 1, True}
print(all(myset))

True
myset = {3, 2, 1, False}
print(all(myset))

False

In this example, one element is False and so the all() function returned False.

## Other Set Functions

We have already looked at some of the set functions like add(), discard(), remove(), pop(), clear(), union(), intersection(), difference(), symmetric_difference() and copy(). Other useful functions are shown below.

### Python isdisjoint()

It returns True if two sets are disjoint. Two sets are disjoint if they have no common element.

set1 = {1, 2, 3, 4, 5}
set2 = {6, 7, 8}

print(set1.isdisjoint(set2))
print(set2.isdisjoint(set1))

True
True

isdisjoint() function returned True in this example because both the sets don’t have any common element.

### Python intersection_update()

It calculates the intersection of two or more sets and assigns the result to the set which calls the function.

Look at the following example to understand the concept better.

set1 = {1, 2, 3, 4, 5, 6}
set2 = {4, 5, 6, 7, 8}
set1.intersection_update(set2)

print('set1:', set1)
print('set2:', set2)

set1: {4, 5, 6}
set2: {4, 5, 6, 7, 8}

set1.intersection_update(set2) - the intersection_update() function assigned the intersection set {4, 5, 6} of sets set1 and set2 to set1 because set1 called the function.

We can also pass more than one set to this function as shown below.

set1 = {1, 2, 3, 4, 5, 6}
set2 = {4, 5, 6, 7, 8}
set3 = {2, 5, 6, 8}
result = set1.intersection_update(set2, set3)

print('intersection_update result:', result)
print('set1:', set1)
print('set2:', set2)
print('set3:', set3)

intersection_update result: None
set1: {5, 6}
set2: {4, 5, 6, 7, 8}
set3: {8, 2, 5, 6}

Here, the intersection set of sets set1, set2 and set3 is assigned to set3.

### Python difference_update()

It calculates the difference of one set from another and assigns the result to the set which calls the function.

Look at the following example.

set1 = {1, 2, 3, 4, 5, 6}
set2 = {4, 5, 6, 7, 8}

set1.difference_update(set2)

print('set1:', set1)
print('set2:', set2)

set1: {1, 2, 3}
set2: {4, 5, 6, 7, 8}

The difference_update() function assigned the difference set {1, 2, 3} to set1 because it called the function.

### Python symmetric_difference_update()

It calculates the symmetric difference of one set from another and assigns the result to the set which calls the function.

set1 = {1, 2, 3, 4, 5, 6}
set2 = {4, 5, 6, 7, 8}

set1.symmetric_difference_update(set2)

print('set1:', set1)
print('set2:', set2)

set1: {1, 2, 3, 7, 8}
set2: {4, 5, 6, 7, 8}

The symmetric_difference_update() function assigned the symmetric difference set {1, 2, 3, 7, 8} to set1 because it called the function.

### Python issubset()

It returns True if a set is a subset of another set, otherwise it returns False. A set set1 is a subset of set set2 if all the elements of a set1 are present in set2.

set1 = {4, 5, 6}
set2 = {4, 5, 6, 7, 8}

print(set1.issubset(set2))  # is set1 subset of set2?
print(set2.issubset(set1))  # is set2 subset of set1?

True
False

All the elements of set1 are present in set2 and thus set1 is a subset of set2. Whereas, set2 doesn’t have all its elements in set1 and so set2 is not a subset of set1.

### Python issuperset()

It returns True if a set is a superset of another set, otherwise it returns False. A set set1 is a superset of set set2 if set1 has all the elements of set2.

set1 = {4, 5, 6}
set2 = {4, 5, 6, 7, 8}

print(set1.issuperset(set2))  # is set1 superset of set2?
print(set2.issuperset(set1))  # is set1 superset of set2?

False
True

set1 doesn’t have all the elements of set2 and thus set1 is not a superset of set2, set2 is a superset of set1.

## Python Frozenset

Frozenset is an immutable variant of set. Sets are mutable and so elements can be added or deleted to sets. Whereas, frozensets are immutable and so their elements can’t be modified once assigned.

A frozenset can be created using the frozenset() function. Like set(), frozenset() also converts a sequence (list, string, tuple) or a collection(dictionary, set) into a frozenset.

The following example creates three frozensets from a list, a string and a set.

frozenset1 = frozenset([1, 2, 3])  # list is converted to frozenset
frozenset2 = frozenset("Codesdope")  # string is converted to frozenset
frozenset3 = frozenset((1, 2, 3, 4))  # set is converted to frozenset
print(frozenset1)
print(frozenset2)
print(frozenset3)

frozenset({1, 2, 3})
frozenset({'o', 'd', 's', 'e', 'C', 'p'})
frozenset({1, 2, 3, 4})

All the functions which can be used with sets can also be used with frozensets, except for those functions which modify the elements. For example, functions like add(), update(), remove(), etc, can’t be used with frozensets.

In the next example, adding an element to a frozenset with add() results in an error.

frozenset1 = frozenset([1, 2, 3])
print(frozenset1)

Traceback (most recent call last):
File "<stdin>", line 2, in <module>
AttributeError: 'frozenset' object has no attribute 'add'

Let’s look at some more examples.

frozenset1 = frozenset({1, 2, 3})
frozenset2 = frozenset({2, 3, 4, 5, 6})

print(len(frozenset1))  # prints no. of elements of frozenset1
print(sum(frozenset1))  # prints sum of elements of frozenset1
print(frozenset2.intersection(frozenset1))  # prints intersection of frozenset1 and frozenset2
print(frozenset2.issuperset(frozenset1))  # prints if frozenset1 is superset of frozenset2

3
6
frozenset({2, 3})
False

### When Should We Use a Frozenset?

We know that the elements of a frozenset can’t be changed and no more elements can be added or deleted from it. Therefore, it can be used to store the data we don’t want the user to change. For example, suppose we have finalized some students in a group. In that case, we can use a frozenset to store the names of those students, so that no one can add, delete or modify their names.

If in this group of students, we don’t want to change the names of the students but want to have the flexibility to add new students or delete existing students from the group, then we should use a set instead.

So now we have learned about all the built-in data types in Python. We have gone through some examples in the course but it is important that you practice questions from the practice section, because the more you practice the better you will understand the concept. In the next section, you are going to make your own functions.

To learn from simple videos, you can always look at our Python video course on CodesDope Pro. It has over 500 practice questions and over 20 projects.
The successful warrior is the average man, with laser-like focus.
- Bruce Lee