Skip to main content

Python Sets & Frozensets

Python Sets​

Set is a high-performance data structure derived from mathematical set theory. Unlike Lists (which are sequences), Sets are unordered collections designed for two specific purposes: enforcing uniqueness and performing mathematical comparisons.


1. Core Characteristics​

  • Unordered & Unindexed:

  • Sets do not record element position. You cannot ask for my_set[0].

  • Note: Because they are unordered, the way they print to the screen might change every time you run the program.

  • Unique Elements Only:

  • Duplicates are strictly forbidden. If you try to add a duplicate, Python silently ignores it.

  • Mutable Structure:

  • You can add or remove items from the set itself.

  • Immutable Elements Hashable:

  • Crucial: The set is mutable, but the items inside must be immutable (Hashable).

  • Allowed: int, float, str, tuple, frozenset.

  • Banned: list, dict, set.

The "Boolean Trap" (True == 1)​

In Python, the boolean True is actually stored as the integer 1, and False as 0. Since sets demand uniqueness, they treat 1 and True as the exact same key.

# 1 and True are duplicates. 0 and False are duplicates.
my_set = {1, True, 0, False}

print(my_set)
# Output: {0, 1} (Python keeps the one that appeared first)

2. Creating Sets​

**1. The Curly Bracket Syntax **{}​

This is the standard way, but it has one major "gotcha."

# Standard Set
colors = {"red", "green", "blue"}

# THE TRAP: Creating an empty set
empty = {} # THIS IS A DICTIONARY, NOT A SET!
real_set = set() # This is the correct way to make an empty set.

2. The set() Constructor​

Used to convert other collections into a set. This is the fastest way to remove duplicates from a list.

raw_data = [1, 2, 2, 3, 3, 3, 4]
clean_data = set(raw_data)

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

3. Modifying Sets - CRUD Operations​

Adding Items​

  • .add(x): Adds a single item.

  • .update(iterable): Adds multiple items from a list, tuple, or another set.

s = {1, 2}
s.add(3) # {1, 2, 3}
s.update([4, 5]) # {1, 2, 3, 4, 5}

Removing Items​

There are four distinct ways to remove items, each with different behavior.

MethodDescriptionBehavior if Item Missing.remove(x)Removes x.❌ Crashes (KeyError).discard(x)Removes x.✅ Does Nothing (Safe).pop()Removes & returns an arbitrary item.❌ Crashes if set is empty.clear()Deletes all items.✅ Safe

> Why is .pop() random?

> > > > Since sets are unordered, there is no "first" or "last" item. .pop() grabs an item based on memory hashing, which can feel random.


4. Mathematical Set Operations​

This is the main reason developers use sets. Instead of writing complex for loops to compare lists, you can use these one-line operations.

**1. Union | or **.union()​

"I want everything from both groups."

  • Combines sets A and B. Duplicates are removed.

  • Code: A | B

**2. Intersection & or **.intersection()​

"I want only the items present in BOTH groups."

  • Code: A & B

**3. Difference - or **.difference()​

"I want items in A that are NOT in B."

  • Code: A - B

**4. Symmetric Difference ^ or **.symmetric_difference()​

"I want items that are in A OR B, but NOT in both." (The opposite of Intersection).

  • Code: A ^ B

Example Scenario:​

Imagine you have two email lists:

subscribers = {"bob@mail.com", "amy@mail.com", "tom@mail.com"}
unsubscribed = {"tom@mail.com", "tim@mail.com"}

# Send emails to active subscribers only (Subscribers minus Unsubscribed)
to_send = subscribers - unsubscribed
print(to_send) # {'bob@mail.com', 'amy@mail.com'}

5. Frozenset - Immutable Set​

A frozenset is to a set ot is a read-only version of a set.

  • Dictionary Keys: You cannot use a regular set as a key in a dictionary because it is mutable. You can use a frozenset.

  • Sets inside Sets: You cannot store a set inside another set (nested sets). You can store a frozenset inside a regular set.

# Creating a Frozenset
fs = frozenset([1, 2, 3])

# fs.add(4) # AttributeError (Cannot modify)

# Using as a Dictionary Key
locations = {
frozenset({10, 20}): "Store A",
frozenset({30, 40}): "Store B"
}

Operation​

You can perform an operation and update the original set in one step.

OperatorMethodDescription=.update()&=.intersection_update()Keep only common items.-=.difference_update()Remove items found in another set.^=.symmetric_difference_update()Keep only items found in one, not both.

A = {1, 2, 3}
B = {3, 4}

A -= B # Remove items in B from A
print(A) # {1, 2}

Summary Table: Set vs List vs Frozenset​

Feature****List []Set {}Frozenset ()Ordered✅ Yes❌ No❌ NoIndexed✅ Yes❌ No❌ NoMutable✅ Yes✅ Yes❌ NoDuplicates✅ Yes❌ No❌ NoLookup SpeedSlow ($O(n)$)Fast ($O(1)$)Fast ($O(1)$)Use CaseData order mattersUniqueness / MathDict Keys / Immutable unique data