## What is `Set` and `frozenset`?

In our previous Data Types blog post, we divided the data types in Python into mutable (Mutable) and immutable (unchangeable) and here we will process both mutable and immutable data types.

`Dictionaries` are a little different because `Dictionaries` consist of two parts; `keys` and `values`, value part can contain all data type but keys part can only be of `string` and `int` type.

## What is `Set`?

It is a data type that contains multiple data types such as list, dictionary, and tuple data types. You can perform all kinds of functions (joining, intersection, etc.) related to sets with this data type.

## `Set` Usage

Let me show you the use of `set` with an example;

``````set = {"Python", 'b', 5, "Baransel"}
``````

It has a very simple usage, but there is something we should pay attention to here if we define an empty set as follows;

``````set = {}
``````

The interpreter will detect it as a `Dictionary`. Well, if you ask how to create an empty set, let me show you;

``````set = set()
``````

we define as.

Let me give another important note about sets: there can be only one element from an element, just like the sets we see here in mathematics. Well, let’s see what happens if we try to add;

``````set = {"Python", 'b', 5, "Baransel", "Python"}

print(set)
# {"Python", 'b', 5, "Baransel"}
``````

Now you will say ok, but we added it, it didn’t make any mistakes, but if you say it shows only one of the same ones while showing, let me show you as follows.

``````set = {"Python", 'b', 5, "Baransel", "Python"}
print(len(set))
# 4
``````

As you can see, when we look at the length of the set, the set sees 4 elements even though we add 5 elements. Since we have given this important note, let me show you how we access the elements of the `Set`.

### Accessing `Set` Items

``````set = {"Python", 'b', 5, "Baransel", "Python"}
print(set)

# TypeError: 'set' object does not support indexing
``````

We got an error in this way because `Set` is not an ordered data type like Dictionaries. So it does not support indexing. Now you will say, why should I use sets, it is true, although the sets seem unnecessary on their own, you will need them when there is more than one `set`, then you will see how necessary the sets are. That’s why I immediately switch to `Set` Method.

Let’s show the `set` methods with the `dir()` function as in every blog post.

### `Set` Methods

``````['__and__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__',
'__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__',
'__iand__', '__init__', '__ior__', '__isub__', '__iter__', '__ixor__',
'__le__', '__len__', '__lt__', '__ne__', '__new__', '__or__', '__rand__',
'__reduce__', '__reduce_ex__', '__repr__', '__ror__', '__rsub__', '__rxor__',
'__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__xor__',
'intersection', 'intersection_update', 'isdisjoint', 'issubset', 'issuperset',
'pop', 'remove', 'symmetric_difference', 'symmetric_difference_update', 'union',
'update']
``````

In this blog post, as in other blog posts, we will not go into `__X__` methods, that is, special methods.

``````['add', 'clear', 'copy', 'difference', 'difference_update', 'discard',
'intersection', 'intersection_update', 'isdisjoint', 'issubset', 'issuperset',
'pop', 'remove', 'symmetric_difference', 'symmetric_difference_update', 'union',
'update']
``````

### `add` Method

This method is the method that allows us to add elements to the `set`;

``````set = {1, 2, 3, 4, 5}
print(set)
# {1, 2, 3, 4, 5, 6}
``````

### `clear` Method

This method returns the `null` value of the method, which serves to clear the `set`.

``````set = {1, 2, 3, 4, 5}
set.clear()
print(set)
# set()
``````

### `copy` Method

This method is the method that allows us to copy the `set`. We can assign a set to another variable without copying it, but when we modify one `set`, the other set also changes, so we use the `copy()` method.

``````set = {1, 2, 3, 4, 5, 6}
set_backup = set()
set_backup = set.copy()
print(set_backup)
# {1, 2, 3, 4, 5, 6}
``````

### `update` Method

This method allows us to refresh the `set`.

``````set = {1, 2, 3, 4, 5, 6}
set_2 = {7, 8, 9, 10}
set.update(set_2)
print(set)
# {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
``````

### `remove` Method

This method is the method for deleting an element from the `set`.

``````set = {1, 2, 3, 4, 5, 6}
set.remove(4)
print(set)
# {1, 2, 3, 5, 6}
``````

If the element we want to delete is not found in the `set`, it gives us the following error;

``````set = {1, 2, 3, 4, 5, 6}
set.remove(8)
print(set)
``````

`KeyError: 8`

### `discard` Method

This method, like the `remove()` method, allows deleting the desired element in the `set`, but it does not give an error if the desired element to be deleted is not in the `set`.

``````set = {1, 2, 3, 4, 5, 6}
set.remove(8)
print(set)
# {1, 2, 3, 5, 6}
``````

### `pop` Method

This method is also used to delete the first element of the `set`.

``````set = {1, 2, 3, 4, 5, 6}
set.pop()
print(set)
# {2, 3, 5, 6}
``````

We have seen some methods for performing various operations on a `set`. If you have noticed, we have seen these methods before when processing list, tuple and dictionary data types.

The methods we are going to process now are used to perform operations on more than one `set`. With these methods, you will be able to answer the question of why `sets`!

Let’s create the sets first;

``````A = {1, 2, 3, 4, 9}
B = {3, 4, 5, 6, 10}
C = {4, 7, 8, 9, 10}
``````

### `union` Method

It is a method that allows two sets to join the `set`.

``````A = {1, 2, 3, 4, 9}
B = {3, 4, 5, 6, 10}
C = {4, 7, 8, 9, 10}

print(A.union(B))
# {1, 2, 3, 4, 5, 6, 9, 10}
``````

In this way, we combined two sets. If you notice, it only wrote once, although both sets have 4 and 5 elements.

If you want, let’s do the union of the three sets now.

``````print(A.union(B.union(C)))
``````

### `intersection` Method

This method gives the intersection of two sets.

``````print(A.intersection(C))
# {9, 4}
``````

Let’s take the intersection of three sets if you want.

``````print(A.intersection(B.intersection(C)))
# {4}
``````

### `intersection_update` Method

This method, like the intersection method, takes the intersection of two methods and performs the update process.

``````A.intersection_update(C)
print(A)

# {9, 4}
``````

### `isdisjoint` Method

This method checks whether the intersection of two sets is empty. Returns `True` or `False` based on the result.

``````A = {1, 2, 3, 4, 9}
C = {4, 7, 8, 9, 10}
# False
``````

It returned `False` because the intersection of the two sets is not empty, it has elements 4 and 9. If we delete two elements, it will return `True`.

``````A = {1, 2, 3,}
C = {4, 7, 8, 9, 10}
# True
``````

### `difference` Method

This method is the method to find the difference between the two.

``````print(A.difference(B))
# {1, 2, 9}
``````

### `difference_update` Method

This method both finds the difference between two sets and updates the `set`:

``````A = {1, 2, 3, 4, 9}
B = {3, 4, 5, 6, 10}
C = {4, 7, 8, 9, 10}

A.difference_update(B)
print(A)
# {1, 2, 9}
``````

### `issubset Metodu` Method

This method questions whether a `set` is a subset of another `set`.

``````A = {1, 2, 5, 8, 9, 12}
B = {1, 2, 5}

print(B.issubset(A))
# True
``````

Here, we have made a query in the form of whether the set B is a subset of the set A.

### `issuperset Metodu Metodu` Method

This method does the opposite of the `issubset` method. It is a method that asks us whether a `set` includes another `set`.

``````A = {1, 2, 5, 8, 9, 12}
B = {1, 2, 5}

print(A.issuperset(B))
# True
``````

We said that set A includes set B, we got the value True because set B is a subset of set A, so we got the result `True`, in the same way, if we do it for set B, it will give `False` value.

## Frozenset

We have just seen the `set` data type, this `frozenset` data type is also the restricted version of the `set` data type. Well, let me explain to you why the restriction is, we divided the data types into mutable (changeable) and immutable (immutable) in Python, and this data type is an immutable data type. That’s why we call it a constrained set, adding, deleting, changing, etc. to this data type. We are unable to process. Let me show you the use of the restricted version of the `Set` data type with an example;

``````restricted_set = frozenset(["Python", 3.9 ,5 ,'B'])
print(kisitli_kume)

# frozenset({"Python", 3.9 ,5 ,'B'})
``````

So what happens if we try to make changes to this data type? For example, let’s try to `delete` an element;

``````restricted_set.remove("Python")

# AttributeError: 'frozenset' object has no attribute 'remove'
``````

As you can see, we got an error that it does not have such a method, not only for deletion, but also for the change type (add, update), if you want, let’s print the existing methods:

``````['copy', 'difference', 'intersection', 'isdisjoint', 'issubset', 'issuperset',
'symmetric_difference', 'union']
``````