Understand the difference b/w python set and frozenset

No, they are not same | Python set vs frozenset | 7 mins read

Python set and frozenset in python are different. The SET data type is used for membership testing and unique element count. Python Frozenset is hashable while the SET in python is not hashable. There are various cases when frozenset is used instead of a python SET. Let's look at each of them in detail in today's Python tutorial.

Table of Contents

Introduction

Welcome back to another exciting tutorial on “Understand the difference between python set and frozenset”. In this Python tutorial, you’ll learn the methods of set and frozenset in python.

You’ll also learn how and when to use a specific set method with the help of examples. In the end, you will see a python set cheat sheet to quickly refresh what we learn so far. Let’s begin our tutorial with an introduction to the Python set and its methods,followed by an introduction to Python frozenset and key differences between them.

If you aren’t following along, I would recommend you to go back where you left or start from here.

What is a Python Set ?

A datatype of a value is an attribute that signifies what type of data that variable holds.
In Python, Datatypes are objects of builtin classes so as python set. A set object is an unordered collection of distinct hashable objects.
In Layman term, elements in the set are unique and there will be no duplicates.
Some key words discussed above are :-
  • Unordered or Unindexed – The place of elements is not fixed.So, it doesn’t support indexing or slicing
  • Mutable – It does support operations like deletion and insertion of elements.
  • Distinct – It doesn’t contain same elements.
  • Hashable ElementsPython Set itself isn’t hashable but should contain hashable elements.

Unlike list and tuples ,set can solve membership queries in O(1) complexity.

Python Set Methods

How to create a Python set ?

Python set can be created using constructor set() or just list out all the elements within curly braces {}.

Example1# Sometime you don’t know the elements before starting so it is advisable to start with an empty set and add elements later.

#Create an empty set
>>> A = set()
>>> type(A)
<class 'set'>

Example2# A set of all natural number under 7

>>> B = {1,2,3,4,5,6}    
>>> type(B)
<class 'set'>

Do not use {} for creating an empty set ,it will create Dictionary instead.

Example3# You can pass an iterable such as list ,tuple within set() constructor to create a python set initialized with iterable values.

>>> iterable = [1,2,3,4,5,6] 
>>> C = set(iterable) 
>>> type(C)
<class 'set'>

Example4# As list and tuples set can also contain heterogeneous values int,char ,string in same set.

#Heterogeneous set
>>> A ={1,2,'one','two'}
>>> print(A)
{1, 2, 'one', 'two'}

Example5# In this example, we want to create power set of {1,2} .In the first case,we use nested set approach and when we run the program ,it gives type error.

In the second approach,we use a term frozenset(will discuss in later section) to make the elements within the python set hashable.

>>> A = {1,2}
>>> pA = {{1},{2},{1,2}}
Traceback (most recent call last):
File "", line 1, in 
TypeError: unhashable type: 'set'
#Right method 
>>> pA = {frozenset((1,)),frozenset((2,)),frozenset((1,2))}
>>> type(pA)
<class 'set'>

To create nested sets such as Power Set ,the inner set should be frozensets objets(Hashable objects)

How to access elements of a python set?

Once you create a set ,you could have to check whether an element is present or not. So for these type of queries, you cannot use indexing like in case of tuples or list.

Instead, you use membership operator ‘in‘ or loop over all the elements.

#print all elements
>>> A = {1,2,3,4,5,6}
>>> for i in A:
print(i,end = ' ')
1 2 3 4 5 6
#membership operation
>>> print(1 in A)
True

How to add new element in python set ?

Set in python are mutable i.e. modification of set is possible.You can use various methods to add new element or number of elements.

1.add() add method takes one argument i.e the value to be added.No error is raised if value is present already .

#Using add() method to add one element
>>> A = {1,2,3,4,5,6}
>>> A.add(7)
>>> print(A)
{1,2,3,4,5,6,7}

2.update() – It takes an iterable as argument i.e list,tuple or set and update the set with those values which aren’t present in set already.

#Using a tuple to add multiple elements 
>>> A = {1,2,3,4,5,6} 
>>> t1 = (6,7,8,9) 
>>> A.update(t1) 
>>> print(A) 
{1, 2, 3, 4, 5, 6, 7, 8, 9}
# Using a list 
>>> A = {1,2,3,4,5,6} 
>>> l1 = [6,7,8,9] 
>>> A.update(l1) 
>>> print(A) 
{1,2,3,4,5,6,7,8,9}
# Using another set 
>>> A = {1,2,3,4,5,6} 
>>> B = {6,7,8,9} 
>>> A.update(B) 
>>> print(A) 
{1,2,3,4,5,6,7,8,9}

How to delete elements from a set?

Any modification or deletion of element from the set in python can be done efficiently using various methods.Each methods has its own pros and cons.

Let us look at each method using an example for better understanding on how they differ and what are their hidden characteristics.

1.remove() – This method will remove the given key from the set and will raise an error if not found.

# This will raise an error as key == 7 is not present in the set
>>> A = {1,2,3,4,5,6} 
>>> A.remove(7) 
Traceback (most recent call last):
 File "", line 1, in 
KeyError: 7
# It will not raise an error
>>> A = {1,2,3,4,5,6} 
>>> A.remove(1) 
>>> print(A)
{2, 3, 4, 5, 6}

2.discard() – This method take single argument i.e the value to be removed.If the value is not present in the set do nothing.

>>> A = {1,2,3,4,5}
>>> A.discard(10)    #No error raised
>>> A.discard(1)
>>> print(A)
{2,3,4,5}

3.clear() – It will clear all elements of the set but not delete set object from memory.

# After using clear method set object A has no elements
>>> A = {1,2,3,4,5,6}
>>> A.clear()
>>> print(A)
set()

4.pop() – It will remove and return the last element from the set.This method is not used very often as set are not ordered.

>>> A = {1,2,3,4,5,6}
>>> x = A.pop()
>>> print(x)
1
>>> print(A)
{2, 3, 4, 5, 6}

5.del – del is not a method .It is a general way to delete any variable in python .In present context it delete the set i.e. free the memory allotted to the set object.

# After del operation , if we print A it will show an error
>>> A = {1,2,3,4,5,6}
>>> del A            # free allotted space for A
>>> print(A)  
Traceback (most recent call last):
File "", line 1, in 
NameError: name 'A' is not defined

Operations on Python Set

These methods can accept any iterable as an argument i.e list,tuple,set etc.

Operator based counterpart requires both arguments to be set.

Every operation on python set is same as we do in set theory using formulas or Venn Diagrams.
Let us look over each operation on sets with an example to clarify the syntax details.

For all the given examples consider:-

A = {2,4,6,8}
B = {3,6,9}

1.union(self,*iterable) – It returns the copy of union of sets as a new set.

>>> C = A.union(B)
>>> print(C)
{2, 3, 4, 6, 8, 9}
#operator based
>>> print(A|B)
{2, 3, 4, 6, 8, 9}

2.intersection(self,*iterable) – It returns the copy of intersection of sets as a new set.

>>> C = A.intersection(B)
>>> print(C)
{6}
#operator based
>>> print(A&B)
{6}

3.intersection_update(*iterable) – Update the set with elements found in all sets.

>> B.intersection_update(A)
>>> print(B)
{6}
#operator based
>>> B&=A
>>> print(B)
{6}

4.difference(self,*iterable) – Return a new set with elements which aren’t in others.

>>> C = A.difference(B)
>>> print(C)
{8, 2, 4}
>>> print(A-B) #operator based
{8, 2, 4}

5.difference_update(self,*iterable) – Update the set with elements that aren’t present in others.

>>> B.difference(A)
>>> print(B)
{9, 3}
>>> B-=A #operator based
print(B)
{9, 3}

6. symmetric_difference(self,iterable) – Return the set of element in either the set but not both.

>>> C = A.symmetric_difference(B)
>>> print(C)
{2, 3, 4, 8, 9}
>>> print(A^B) #operator based
{2, 3, 4, 8, 9}

7. symmetric_difference_update(self,iterable) – Update the set with element in any set but not both.

>>> B.symmetric_difference_update(A)
>>> print(B)
{2, 3, 4, 8, 9}
#operator based
>>> B^=A
>>> print(B)
{2,3,4,8,9}

8.issubset(self,iterable) – Check if every element of set is in iterable.

>>> B.issubset(A)
False
>>> B<=A
False

9.issuperset(self,iterable) – Check if every element of iterable is in set.

>>> B.issuperset(A)
False
>>> B>=A
False

Frozenset

As discussed above, python set itself is not hashable but the elements present inside should be hashable. Do you think of any case that requires a set to be hashable ?

Consider a case if you want to make python set a key in dictionary. Well , it can be done but a naive approach would throw an error.

For example,

>>> A = {1,2}
>>> d1 = {}
>>> d1[A] = 1
Traceback (most recent call last):
File "", line 1, in 
TypeError: unhashable type: 'set'

The datatype which we want to use as a dictionary key should be hashable and that is where frozenset came into play.

>>> A = frozenset((1,2))
>>> d1 = {}
>>> d1[A] = 1
>>> print(d1)
{frozenset({1,2}):1}

In nested set, the inner sets are frozensets .For example, if we want to show a power set then inner set are frozensets.

Python Set Vs FrozenSet

Python Set Vs Frozenset

Cheat Sheet

Operation Operator explanation
len(s)
Cardinality of set s
x in s
Test membership of x in s
x not in s
Test non-membership of x in s
s.copy()
Make a copy of given set
s.add()
Add single element x in s
s.remove()
Remove element x from set s (Raise error if key not found)
s.discard()
Remove element x from set s (No error raised)
s.pop()
Remove and return last element of set
s.clear()
Delete all the elements of the set i.e. Make set an empty set
s.union(*t)
s|t
Return union of sets as new set
s.update(*t)
s|=t
Assign set s to the union of sets.
s.intersection(*t)
s & t
Return intersection of sets as new set
s.intersection_update(*t)
s&=t
Assign set s to the intersection of sets
s.difference(*t)
s-t
Return set difference s with *t as new set
s.difference_update(*t)
s-=t
Assign set difference s with *t to set s.
s.symmetric_difference(t)
s^t
Return symmetrc difference of s and t as new set.
s.symmetric_difference_update(t)
s^=t
Assign set s to symmetric difference of s and t
s.issubset(t)
s<=t
Test whether every element of s is in t.
s.issuperset()
s>=t
Test whether every element of t is in s

Conclusion

If you are reading this , I want you to know that you have made a very clear understanding of python sets and their use . Now, you can answer any query regarding python set with an ease . In the next tutorial, we will talk about some new stuff regarding python .

Last but not the least, do leave your feedback and suggestions. We would love to hear your feedback.

Till then , keep coding !