# Introduction to Python Sets

## Getting Started

Sets are probably the most unique data structure collections we've covered so far. We'll focus on where they excel the most and cover some crucial characteristics and nuances.

## What are Sets in Python?

Sets are defined using curly braces `{}` or the `set()` constructor, and they can store multiple elements, but unlike lists and tuples, they have no order and cannot contain duplicate items.

Moreover, sets provide several set operations, such as union and intersection, which can be useful for performing mathematical operations on collections of data.

## Creating a Set

Creating a set in Python is quite straightforward.

Note: Inside sets, we can't have duplicate items

So, let's illustrate something intriguing by starting with a list containing duplicate elements, and removing those using sets while also learning the basic syntax.

``````nums = [1, 2, 2, 3, 4] # List with duplicate integers

unique_values = set(nums) # The set constructor

print(unqiue_values) # Output: {1, 2, 3, 4}
``````

As we can notice, we have a new set containing only unique elements.

Moving forward, we'll create another set using the curly brace syntax.

``````new_set = {"Python", "JavaScript", "Java"}

print(new_set) # Output: {'JavaScript', 'Java', 'Python'}

print(type(new_set)) # Output: <class 'set'>
``````

## Accessing Elements in Sets

The contents in a set are not in a specific sequence. As a result, we cannot access the elements by index. However, we can loop over the set and create a desired output, or perform a membership test.

``````languages = {"Python", "JavaScript", "Java"}

for elements in languages:
print(elements)
``````
``````languages = {"Python", "JavaScript", "Java"}

print("Python" in languages) # Output: True
``````

While the elements within a set must be of an immutable data type, the set itself can be altered. There are several ways we can achieve this, including through mathematical operations and other methods.

Furthermore, since sets are unordered collections, the order in which we add or remove items isn't guaranteed to be the same. The elements inside are stored in an arbitrary order.

So, to add a single element to a set, we can use the `add()` method.

``````example_set = {"pizza", "burger", "tacos"}
print(example_set)
``````

Or, to do the opposite we can leverage the `remove()` method.

``````example_set = {"pizza", "burger", "tacos", "ramen"}
example_set.remove("burger")
print(example_set)
``````

We can also modify sets with the `update()` method which proves useful for adding multiple elements at once. It's possible to pass another set, a list as in the example, or any other iterable object.

``````example_set = {"pizza", "tacos", "ramen"}
example_set.update(["chicken", "steak", "sushi"])
print(example_set)
``````

## Mathematical Operations

Sets also excel at mathematical-like operations. They're capable of performing mathematical operations that enable us to merge, intersect, subtract, and perform symmetric differences between them.

``````first_set = {1, 2, 3, 4, 5}
second_set = {5, 7, 9}

# Union using the pipe operator (|)
print(first_set | second_set) # {1, 2, 3, 4, 5, 7, 9}

# Intersection using the ampersand operator (&)
print(first_set & second_set) # {5}

# Difference using the minus operator (-)
print(first_set - second_set) # {1, 2, 3, 4}

# Symmetric Difference using the caret operator (^)
print(first_set ^ second_set) # {1, 2, 3, 4, 7, 9}

# Union using the union method
print(first_set.union(second_set)) # {1, 2, 3, 4, 5, 7, 9}

# Intersection using the intersection method
print(first_set.intersection(second_set)) # {5}

# Difference using the difference method
print(first_set.difference(second_set)) # {1, 2, 3, 4}
``````

Each of these operations returns a new set that contains the result of the operation

## Why use Sets

Sets can incredibly useful in Python for a variety of reasons. Firstly, they're optimized for membership tests, meaning that checking for elements in a set is generally faster than other collections.

Additionally, they're used in conjunction with dictionaries. When a dictionary is created, its keys are automatically converted into a set. This is because dictionaries are implemented as hash tables, and sets are well-suited for representing the keys in a hash table.

### Useful Resources

Official Python Documentation on Sets and Data Structures

Intro to Python Dictionaries

Introduction to Python Lists

Introduction to Python Tuples