# Comprehensive Python

### Python Datatypes: Sets

Ladies and gentlemen, welcome to our final part of the datatype series, the `sets`. This tutorial will be much easy and funny to you if you liked mathematics in your high schools.

Huh! wait a minute... Didn't we learn something about sets in our getting started?, hahaha, obviously we didn't.
That was just the getting started, and now is the advanced level for us to learn everything we need to know in Python. Let's dismantle the python `set` piece-by-piece.

## Python Sets Datatype

What did the teacher say at the high school about sets?
Wasn't it that a Set is a collection of distinct objects, considered as an object in its own. right? and in fact, that is the real meaning of sets in python.
In fact, the `Set` in python is the unordered collection of unique elements.
If you read correctly in the above definition, a set has only one entry of its items, ie no duplicates.
As a result of being Unordered, the python sets do not support `Indexing`, and just like `tuples`, the Set is immutable.
A set data is within the oppening and close brackets `{ }` and data within it are seperated by commas. Enough has been talked about the python sets, let's now see how we can thwart against the python sets.

## Working With Sets

As already said, a python set items are within two curly braces,t he code snippet below shows how we can initialize a python set.
`>>> set1 = set()`
As a result of lack of indexing, we can add items in the python set during the variable initialization or using special function called `add` All the items looks like that in lists and are seperated by the commas as in below example:
`>>> set1 = {1,2,3}`
The items in the set are also not accessed using indeces as can't be edited with indeces.
Let's now take a look at some of the functions used for manipulating python sets.

## Python Set Functions and Methods

As already said, python sets are the special data type and must be handled with care.
It is impossible for us to reassign the Set data, and it is difficult for us to add data in sets once it is built, unless we use its function, and some of them include `sum, min, max` etc as we did in previous tutorials.
below are some of the functions we may use in sets.

Example1
`>>> set1 = [1,2,3]`
`>>> sum(set1) # 6`
The `sum()` function takes an iterable object containing numbers and returns the addition of all of them.
The work flow goes like this :
item1 + item2+...+itemN
Example2
`>>> min(set1) # 1`
The `min()` function returns the minimum/the smallest of all the items in the set.

Example3
`>>> max(set1) # 3`
The `max()` function is the opposite of the `min()` function, and returns the greatest/biggest item in the set.

Although there are this functions to use when working with the sets, the following are the ones built for sets.

`.add()`
Just as the name narrates, the method `add()` inserts the item into the set if the item is not available, and if the item is already in the set, then this method does nothing. Here is how we can achieve this:
`>>> set1 = {1}`
`>>> set1.add(2)`
`>>> print(set1) # {1, 2}`
`.clear()`
This is the built-in method for the set datatype, just as we did with `clear()` in lists, it removes all the elements of the concerned set.
Here is an example of how we can manipulate the data using the `clear()` function.
`>>> set1 = {1}`
`>>> set1.clear()`
`>>> print(set1) # set()`

`.copy()`
This is the built-in method for the set datatype, and it returns the shallow duplicate of the concerned set.
Here is an example of how we can use `copy()` function to store the replica of our data.
`>>> set1 = {1}`
`>>> set2 = set1.copy()`
`>>> print(set2) # {1}`

`.difference(set, [others])`
This is a set function for calculating the difference of two or more sets. It returns all the items that are available in concerned set but not to the passed set(s).
Here is how it goes:
`>>> set1 = {1, 5, 3}`
`>>> set2 = set1.difference({1, 2, 3})`
`>>> print(set2) # {5, 3}`

`.difference_update(set, [others])`
This set function also calculates the difference of two or more sets. It however removes the items of the concerned set that are also available in the other set(s).
Here is how it goes:
`>>> set1 = {1, 5, 3}`
`>>> set1.difference_update({1, 2, 3})`
`>>> print(set1) # {5}`

`.discard(item)`
This function removes an item from the set if the item is available in the set.If it is not in the set, then it does nothing.
Here is how it goes:
`>>> set1 = {1, 5, 3}`
`>>> set1.discard(3)`
`>>> print(set1) # {1, 5}`

`.intersection(set)`
This is a set function for calculating the similar items of two or more sets. It returns all the items that are available in concerned set and the parsed sets as a new set.
Here is how it goes:
`>>> set1 = {1, 5, 3}`
`>>> set2 = set1.intersection({1,2,3})`
`>>> print(set2) # {1}`

`.intersection_update(set)`
Updats the set with the intersection of itself and the other parsed set.
In other words, it removes all the elements of a set that are not available in the parsed set.
`>>> set1 = {1, 5, 3}`
`>>> set1.intersection_update({1,2,3})`
`>>> print(set1) # {1}`

`.isdisjoint(set)`
This set function returns `True` if the two sets are have no any intersection and returns `False` otherwise.
`>>> set1 = {1, 5,3}`
`>>> set2 = set1.isdisjoint({1,2,3})`
`>>> print(set2) # False`

`.issubset(set)`
This function returns `True` is the concerned set is the subset of a passed set, and returns False otherwise(ie if the set is a superset).
Here is how it goes:
`>>> set1 = {1, 5, 3}`
`>>> set2 = set1.issubset({1,2,3})`
`>>> print(set2) # False`
`>>> print(set1.issubset({1,7,5,3,9}) True`
`.issupperset(set)`
This function returns `True` is the concerned set is the supperset of a parsed set, and returns False otherwise(ie if the set is a subset).
Here is how it goes:
`>>> set1 = {1, 5, 3}`
`>>> set2 = set1.issupperset({1,2,3})`
`>>> print(set2) # False`
`>>> print(set1.issupperset({1,3}) True`
`.pop()`
This function returns the arbitrary(random) item in the set if a set is not empty.
If the set is null, it raises an `KeyError`.
Here is how it goes:
`>>> set1 = {1, 5, 3}`
`>>> set2 = set1.pop()`
`>>> print(set2) # 1`

`.pop()`
This function removes an item in the set if a set is not empty.
If the set is null, and/or an item is not in the set, it raises an `KeyError`.
Here is how it goes:
`>>> set1 = {1, 5, 3}`
`>>> set1.remove(5)`
`>>> print(set2) # {1, 3}`

`.symmetric_difference(set)`
This function returns a set of items that are in exactly(only) one of the sets and not the other set.
Here is how it goes:
`>>> set1 = {1, 5, 3}`
`>>> set2 = set1.symmetric_difference({2,3,4})`
`>>> print(set2) # {1, 5,2,4}`

`.symmetric_difference_update(set)`
This function updates a set with the items that are in exactly(only) one of the sets and not the other set.
Here is the agreed method on how it works:
`>>> set1 = {1, 5, 3}`
`>>> set1.symmetric_difference_update({2,3,4})`
`>>> print(set1) # {1, 5,2,4}`

`.union(set)`
This function returns a set of items that are in either of the sets,that is the union of the two sets. If an item is also available in both sets, then only one copy of it is used.
Here is how it goes:
`>>> set1 = {1, 5, 3}`
`>>> set2 = set1.union({2,3,4})`
`>>> print(set2) # {1,2,3,4,5}`

`.update(set)`
This function updates a set with the union of itself and te other. Note that the original set is the one affected.
Here is how it goes:
`>>> set1 = {1, 5, 3}`
`>>> set1.update({2,3,4})`
`>>> print(set2) # {1, 5,3,2,4}`

Congratulations guys, you are now done learning python datatypes, let's relax and don't forget to take an Assignment