A set represent an unordered collection of unique elements. This data type represents the Mathematical notion of set. 

Sets in Python are mutable, however,  they can only contain immutable elements such as strings, tuples, integers, etc.  A  set cannot contain a mutable element such as a list , a dictionary or even another set. 

In Python elements in a set are enclosed in curly braces, {}.  However, to initialize an empty set, we can only use the builtin set() function. as shown below:

set()

We cannot use empty curly braces , this is because, the curly braces are also used in Python dictionaries. Python will interpret empty curly braces as an empty dictionary instead of an empty set.

x = {}
type(x)
//<class 'dict'>

But for a non-empty set there is no ambiguity because the syntax for set elements  and dictionaries are different. It is therefore fine to use the curly braces to initialize a non-empty set:

Examples:

S = {1, 2, 3, 4, 5}
type(S)
//<class 'set'>
S1 = {'Python', 'Javascript', 'CSS'}
S2 = {1.0, 2.0, 3.0}

Elements in a set are unique, this means that an item will only be included once even if it appears more than once during initialization. Examples

S = {'Python', 'Python', 'Python', 'Python'}
print(S)
//{'Python'}
S1 = {'Python', 'C++', 'Javascript', 'Java', 'CSS', 'Html', 'CSS', 'Java', 'C++'}
print(S1)
//{'Java', 'C++', 'Javascript', 'Html', 'Python', 'CSS'}

The set() function is also used to cast other supported  sequential types such as lists, tuples, etc. to sets. Examples:

set( [1, 2, 3] )  #list to set
//{1, 2, 3}
set( ('Python', 'CSS', 'PHP') )  #tuple to set
//{'CSS', 'Python', 'PHP'}

As we said the elements in a set are also unordered. While Python will sometimes show the elements in their order of initialization, this is not a guaranteed order like in other data types such as lists and tuples. This also means that we cannot access elements in a set through indexing or slicing.

Sets in Python use a hashtable implementation to efficiently store and retrieve elements based on their hash value. Since lists , dictionaries and sets are mutable and their hash values can change, they are not allowed as elements in a set. Trying to store unhashable elements in a set will raise a TypeError, as shown below:

S = {[2, 3], [2, 3]}
//TypeError: unhashable type: 'list'

Set Operations and Methods

Most operations common to other sequential data types such as concatenation , repetition , indexing and slicing are not applicable to sets. This mostly stems from the fact that items in sets are unordered and unique, most of this operations such as concatenation and indexing implies a specific order while others such as repetition would violate the uniqueness property of sets. Instead, sets have some other unique set of operations , which we will discuss here.

Set Union

The union of two sets is the set of all the elements of both the sets without duplicates. You can use the union() method or the | syntax to find the union of a Python set.

Examples:

S1 = {1, 2, 3, 4, 5}
S2 = {3, 4, 5, 6, 7}
S1.union(S2)
//{1, 2, 3, 4, 5, 6, 7}
S1 | S2
//{1, 2, 3, 4, 5, 6, 7}

Set Intersection

The intersection of two sets is the set of all the common elements of both sets. You can use the intersection() method or the & operator to find the intersection of a Python set.

Examples:

S1 = {0, 1, 2, 3, 4, 5}
S2 = {6, 7, 8, 9}
S3 = {0, 2, 4, 6, 8}
S1.intersection(S2) #no common elements, therefore, returns an empty set.
//set()
S1 & S3
//{0, 2, 4}
S2 & S3
//{8, 6}

Set Difference

The difference between two sets is the set of all the elements in first set that are not present in the second set. You can use the difference() method or the - operator to achieve this in Python.

​S1 = {0, 1, 2, 3, 4, 5}
S2 = {6, 7, 8, 9}
S3 = {0, 2, 4, 6, 8}
S1.difference(S2)
//{0, 1, 2, 3, 4, 5}
S2.difference(S1)
//{8, 9, 6, 7}
S1 - S3
//{1, 3, 5}
S2 - S3
//{9, 7}
​

Set Symmetric Difference

The symmetric difference between two sets is the set of all the elements that are either in the first set or the second set but not in both. We can use the symmetric_difference or the operator.

Examples

​
S1 = {0, 1, 2, 3, 4, 5}
S2 = {6, 7, 8, 9}
S3 = {0, 2, 4, 6, 8}
S1.symmetric_difference(S2)
//{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
S1 ^ S3
//{1, 3, 5, 6, 8}
S2 ^ S3
//{0, 2, 4, 7, 9}
​

Other set Methods:

issubset():

Syntax:

S1.issubset(S2)

This methods returns True if all the elements of set S1 are in S2 , else False.

Examples:

S1 = {1, 3, 5, 7, 9}
S2 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
S3 = {0, 2, 4, 6, 8}
S1.isubset(S2)
//True
S3.issubset(S2)
//True
S2.issubset(S1)
//False
S3.issubset(S1)
//False

issuperset()

Syntax:

S1.issuperset(S2)

This method returns True if all the elements in S2 are in S1, else False.

 Examples:

S1 = {1, 3, 5, 7, 9}
S2 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
S3 = {0, 2, 4, 6, 8}
S2.isuperset(S1)
//True
S2.issubset(S3)
//True
S1.issuperset(S2)
//False
S3.issuperset(S1)
//False

isdisjoint():

This method returns True if there are no common elements between S1 and S2, else False.

Examples:

S1 = {1, 3, 5, 7, 9}
S2 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
S3 = {0, 2, 4, 6, 8}
S1.isdisjoint(S2)
//False
S1.isdisjoint(S3)
//True

add():

Syntax:

S.add(x)

This method is used to add an element, x to the Set S, if the element already exist in the set, it is ignored in order to maintain the uniqueness property.

Examples; 

S = {1, 3, 5}
S.add(7)
print(S)
//{1, 3, 5, 7}
S.add(9)
print(S)
//{1, 3, 5, 7, 9}
S.add(5)
print(S)
//{1, 3, 5, 7, 9}

update():

Syntax:

S.update(seq)

This method is used to add all the elements of the sequence, seq to the set S.

Examples:

S = {1, 3, 5}
S.update([7, 9, 11])
print(S)
//{1, 3, 5, 7, 9, 11}

remove():

Syntax:

S.remove(x)

This method removes element x from set S, a KeyError is raised if element x is not found in the set.

Examples:

S = {1, 3, 4, 5, 7, 9}
S.remove(4)
print(S)
//{1, 3, 5, 7, 9}
S.remove(10)
//KeyError: 10

discard():

Syntax:

S.discard(x)

Removes element x from set S, but unlike remove(), no KeyError is raised if the element is not found.

Examples:

S = {1, 3, 4, 5, 7, 9}
S.discard(4)
print(S)
//{1, 3, 5, 7, 9}
S.discard(10)
print(S)
//{1, 3, 5, 7, 9}

pop():

Syntax:

S.pop() 

This method removes and returns a random element in the set S, a KeyError is raised if the set is empty.

Examples:

S = {0, 2, 4}
S.pop()
//2
S.pop()
//0
S.pop()
//4
S.pop()
//KeyError: 'pop from an empty set'

clear():

Syntax:

S.clear()

 Removes all elements from set S effectively making it an empty set.

Examples:

S= {1, 2, 3, 4, 5}
S.clear()
print(S)
//set()