# Data Structures - Frozenset

In this tutorial you will learn all about the frozenset data type. Learn when it is best to use a frozenset, how to create frozensets and how to get elements, and much more.

## Python frozenset

**Python frozenset** is a type of set that is immutable (can't be changed). Like set, it is an unordered collection of unique objects. The objects should be hashable (such as integers, booleans, strings, tuples).

Because frozenset is immutable, elements of the frozenset remain the same after creation.

## Frozenset vs set - Main Differences

In Python **frozensets and sets are quite the same**. The main difference is their mutability - once a frozenset is created, objects can't be added or removed. However, “regular” sets can be changed after their creation. Moreover, **forzensets can be used as keys in dictionaries**. Here is a table that sums the differences.

Set | Frozenset |
---|---|

Mutable | Immutable |

Unhashable | Hashable |

Can't be used as keys in dictionaries | Can be used as keys in dictionaries |

Contains unique elements | Contains unique elements |

Iterable | Iterable |

## How to Create Frozensets

Using the forzenset() function you can create a frozenset. The forzenset() is a built-in function which takes an iterable object and make it a frozen set - (immutable set). When no object is given, the function creates an empty frozenset. Here is an example:

```
# frozenset()
my_list = [1, 2, 3, 4]
my_frozenset = frozenset(my_list)
print(my_frozenset)
empty_frozenset = frozenset()
```

## Convert a Frozenset into a List in Python

The best way to convert a frozenset into a list is by using the list() function. This is a built-in function that converts different datatypes into the list data-type. You can use it in order to convert a frozenset into a list. Watch the example below.

```
# list()
my_frozenset = frozenset([1, 2, 3, 4])
my_list = list(my_frozenset)
print(my_list)
```

## When to Use Frozensets?

One of the main reasons to use a forzenset instead of a set, is if you would like it to be a **key in a dictionary**. Since frozensets are immutable and hashable, they can be used as keys in dictionaries or as objects of another sets. Regular sets can't do that.

In addition, sometimes use of frozenset is considered to be **“best practice”**. As a programmer, you want your code to be clean and descriptive. If the set you use **shouldn't be changed**, it is best to use a frozenset. This will prevent other programmers (or even you in the future) to handle the code in an improper way.

## When to Use Sets?

In general sets are much more popular than frozensets. Unless you want use the object as a key in a dictionary or to make sure that elements can't be added or removed once created, it is best to use a set.

## Which is Faster - Frozenset VS Set Performance

In general, frozensets and sets implementation is very similar. Therefore, in terms of speed, they perform the same. Don’t hesitate to use one over the other if runtime is on your mind.

# Frozenset - Functions and Methods

## How to Access Elements of Frozensets

Frozenets are unordered data structures. That means you can't retrieve items in a set using their indexes as you used to do with lists. However, you can retrieve an arbitrary element. Here are some ways to get elements from a frozenset.

### Iterate Over a Frozenset in Python

Iteraotrs are a great way to get elements from a frozenset. After creating an iterator, get the next item using the next() function. Here is an example:

```
# iter
my_frozenset = frozenset([1, 2, 3, 4])
my_iter = iter(my_frozenset)
print(next(my_iter))
print(next(my_iter))
```

### Retrieve all Elements of a Frozenset

If you wish to retrieve all the elements, you can iterate over the whole frozenset.

```
# iter
my_frozenset = frozenset([1, 2, 3, 4])
for item in my_frozenset:
print(item)
```

## Frozenset Union

**Union** - the union of a collection of sets is the set of all elements in the collection.

The frozenset union() is a built-in function that returns the union of frozensets as a new frozenset. The new frozenset contains all the elements that are in either frozensets.

```
# Union()
a_frozenset = frozenset([1, 2, 3, 4])
b_frozenset = frozenset([2, 3, 4, 5])
my_union = a_frozenset.union(b_frozenset)
print(my_union)
```

## Frozenset Copy

The copy() function is a built-in function that returns a shallow copy of a frozenset. Meaning a brand new frozneset is created. However, the new frozenset has the same references to the objects found in the original.

```
# Copy()
my_frozenset = frozenset([1, 2, 3, 4])
another_one = my_frozenset.copy()
print(another_one)
```

## Frozenset Difference

Frozenset difference() is a built-in function that returns the difference of two or more frozensets as a new frozenset. The new frozenst contains all elements that are in this frozenset but not the others.

```
# Frozenset Difference
a_frozenset = frozenset([1, 2, 3, 4])
b_frozenset = frozenset([2, 3, 4, 5])
dif_frozenset = a.difference(b)
print(dif_frozenset)
```

## Frozenset Intersection

Frozenset intersection() is a built-in function that returns the intersection of two or more frozensets as a new frozenset. The new frozenset contains all elements that are in both frozensets.

```
# Frozenset Intersection
a_frozenset = frozenset([1, 2, 3, 4])
b_frozenset = frozenset([2, 3, 4, 5])
inter_frozenset = a_frozenset.intersection(b_frozenset)
print(inter_frozenset)
```

## Frozenset Isdisjoint

Frozenset isdisjoint() is a built-in function that returns True if two frozensets are disjoint sets (they have no common elements). If not, it returns False.

```
# Frozenset Isdisjoint
a_frozenset = frozenset([1, 2, 3, 4])
b_frozenset = frozenset([2, 3, 4, 5])
c_frozenset = frozenset([5, 6])
print(a_frozenset.isdisjoint(b_frozenset))
print(a_frozenset.isdisjoint(c_frozenset))
```

## Frozenset Issubset

A **subset** is a set of which all the elements are contained in another set.

The frozenset issubset() is a built-in function that returns True if another frozenset contains this frozenset. If not, it returns False.

```
# Frozenset Issubset
a_frozenset = frozenset([1, 2, 3, 4])
b_frozenset = frozenset([1, 2, 3])
print(a_frozenset.issubset(b_frozenset))
print(b_frozenset.issubset(a_frozenset))
```

## Frozenset Issuperset

A **superset** is a set that contains all the elements another set.

The frozenset issuperset() is a built-in function that returns True if this forzenset contains another frozenset. If not, it returns False.

```
# Frozenset Issuperset
a_frozenset = frozenset([1, 2, 3, 4])
b_frozenset = frozenset([1, 2, 3])
print(a_frozenset.issuperset(b_frozenset))
print(b_frozenset.issuperset(a_frozenset))
```

## Frozenset Symmetric Difference

The frozenset symmetric_difference() is a built-in function that returns the symmetric difference of two sets as a new set. Meaning all elements that are in exactly one of the sets.

```
# Frozenset Symmetric Difference
a_frozenset = frozenset([1, 2, 3, 4])
b_frozenset = frozenset([1, 2, 3])
print(a_frozenset.symmetric_difference(b_frozenset))
```

# Python Frozenset - Exercise

One of the great advantages of frozensets is that they can be used as keys in dictionaries. This characteristic can be very useful.

Imagine you divide a class into groups. Let’s say there is a competition, and you want to keep track of the score. Create 4 different forzensets, each contains the names of the students in each group. Try changing the score of each group. This fun exercise can be a great way to learn how to use frozensets.

```
# Write your code here:
```