Python Programming Data Structures
Unordered Unique Elements

Python Sets Complete Guide

Learn Python sets - creation, methods, set operations, set theory with practical examples and real-world applications for efficient unique data handling.

Unordered

No indexing

Unique

No duplicates

Set Operations

Union, Intersection

Fast Lookups

O(1) membership

1. Introduction to Sets

Sets are unordered, mutable collections of unique, hashable elements. They are optimized for membership testing and mathematical set operations.

Python sets diagram: unordered collection of unique elements, curly braces set literal, union intersection difference operations, and fast membership testing
Python sets: Store unique values, test membership quickly, and combine sets with union, intersection, and difference.

Key Properties

  • Unordered — No index-based access
  • Unique elements — No duplicates allowed
  • Mutable — Can add/remove elements
  • Hashable elements — Elements must be immutable/hashable
  • Fast membership — Very fast membership testing (O(1) average)
  • Set algebra — Union, intersection, difference, symmetric difference

2. Creating Sets

Creating sets
# Empty set (note: {} creates empty dict)
empty_set = set()
print(type(empty_set))  # <class 'set'>

# Wrong way - this creates a dict
wrong = {}
print(type(wrong))  # <class 'dict'>

# Set with elements
fruits = {'apple', 'banana', 'orange', 'apple'}
print(fruits)  # {'banana', 'orange', 'apple'} (duplicates removed, order arbitrary)

# Using set() constructor
numbers = set([1, 2, 3, 3, 4, 4, 5])
print(numbers)  # {1, 2, 3, 4, 5}

# From string
chars = set("hello")
print(chars)  # {'h', 'e', 'l', 'o'} (unique characters)

# From range
range_set = set(range(5))
print(range_set)  # {0, 1, 2, 3, 4}

# Set with mixed types (must be hashable)
mixed = {1, 'hello', (1, 2), True}
print(mixed)  # {1, 'hello', (1, 2)} (True=1, so no duplicate)

# Invalid - unhashable types
# invalid = {[1, 2], {3, 4}}  # TypeError: unhashable type: 'list'

3. Accessing Set Elements

Sets are unordered, so you cannot access by index. Instead, you check membership or iterate.

Membership and iteration
fruits = {'apple', 'banana', 'orange', 'mango'}

# Membership testing
print('banana' in fruits)    # True
print('grape' in fruits)     # False
print('apple' not in fruits) # False

# Iterating through set
for fruit in fruits:
    print(fruit)

# Check if set is empty
if fruits:
    print("Set has elements")

# Get length
print(len(fruits))  # 4

# Min and max (if elements are comparable)
numbers = {1, 5, 2, 8, 3}
print(min(numbers))  # 1
print(max(numbers))  # 8
print(sum(numbers))  # 19

4. Adding and Removing Elements

Adding Elements

add, update
colors = {'red', 'green'}

# Add single element
colors.add('blue')
print(colors)  # {'red', 'green', 'blue'}

# Adding duplicate has no effect
colors.add('red')
print(colors)  # {'red', 'green', 'blue'} (unchanged)

# Update with multiple elements (from iterable)
colors.update(['yellow', 'purple', 'orange'])
print(colors)  # {'red', 'green', 'blue', 'yellow', 'purple', 'orange'}

# Update with another set
more_colors = {'cyan', 'magenta'}
colors.update(more_colors)
print(colors)

Removing Elements

remove, discard, pop, clear
colors = {'red', 'green', 'blue', 'yellow', 'purple'}

# remove() - raises KeyError if element not found
colors.remove('green')
print(colors)  # {'red', 'blue', 'yellow', 'purple'}
# colors.remove('black')  # KeyError!

# discard() - no error if element not found
colors.discard('blue')
print(colors)  # {'red', 'yellow', 'purple'}
colors.discard('black')  # No error, does nothing

# pop() - removes and returns arbitrary element
popped = colors.pop()
print(f"Removed: {popped}")
print(colors)

# clear() - remove all elements
colors.clear()
print(colors)  # set()

5. Set Operations

Union (|)

Union
set_a = {1, 2, 3, 4, 5}
set_b = {4, 5, 6, 7, 8}

# Union - elements in either set
union1 = set_a.union(set_b)
union2 = set_a | set_b
print(union1)  # {1, 2, 3, 4, 5, 6, 7, 8}
print(union2)  # {1, 2, 3, 4, 5, 6, 7, 8}

# Multiple sets
set_c = {8, 9, 10}
union_all = set_a | set_b | set_c
print(union_all)  # {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

Intersection (&)

Intersection
set_a = {1, 2, 3, 4, 5}
set_b = {4, 5, 6, 7, 8}

# Intersection - elements in both sets
intersection1 = set_a.intersection(set_b)
intersection2 = set_a & set_b
print(intersection1)  # {4, 5}
print(intersection2)  # {4, 5}

# Multiple sets
set_c = {3, 4, 5, 9}
intersection_all = set_a & set_b & set_c
print(intersection_all)  # {4, 5}

Difference (-)

Difference
set_a = {1, 2, 3, 4, 5}
set_b = {4, 5, 6, 7, 8}

# Difference - elements in set_a but not in set_b
diff1 = set_a.difference(set_b)
diff2 = set_a - set_b
print(diff1)  # {1, 2, 3}
print(diff2)  # {1, 2, 3}

# Difference in reverse - elements in set_b but not in set_a
diff3 = set_b - set_a
print(diff3)  # {6, 7, 8}

Symmetric Difference (^)

Symmetric difference
set_a = {1, 2, 3, 4, 5}
set_b = {4, 5, 6, 7, 8}

# Symmetric difference - elements in either but not both
sym_diff1 = set_a.symmetric_difference(set_b)
sym_diff2 = set_a ^ set_b
print(sym_diff1)  # {1, 2, 3, 6, 7, 8}
print(sym_diff2)  # {1, 2, 3, 6, 7, 8}

6. Set Methods

Subset and Superset

issubset, issuperset, isdisjoint
set_a = {1, 2, 3, 4, 5}
set_b = {2, 3, 4}
set_c = {1, 2, 3, 4, 5}

# issubset - all elements of set_b are in set_a
print(set_b.issubset(set_a))  # True
print(set_b <= set_a)         # True
print(set_b <= set_c)         # True

# Proper subset (strict)
print(set_b < set_a)   # True (set_b is proper subset)
print(set_c < set_a)   # False (equal)

# issuperset - set_a contains all elements of set_b
print(set_a.issuperset(set_b))  # True
print(set_a >= set_b)           # True

# Proper superset
print(set_a > set_b)   # True
print(set_a > set_c)   # False (equal)

# Disjoint - no common elements
set1 = {1, 2, 3}
set2 = {4, 5, 6}
set3 = {3, 4, 5}
print(set1.isdisjoint(set2))  # True
print(set1.isdisjoint(set3))  # False

Set Modification Methods

update, intersection_update, difference_update
set_a = {1, 2, 3, 4, 5}
set_b = {4, 5, 6, 7, 8}

# Update with union (adds elements)
set_a.update(set_b)
print(set_a)  # {1, 2, 3, 4, 5, 6, 7, 8}
set_a = {1, 2, 3, 4, 5}  # reset

# Intersection update (keeps only common elements)
set_a.intersection_update(set_b)
print(set_a)  # {4, 5}
set_a = {1, 2, 3, 4, 5}  # reset

# Difference update (removes elements in set_b)
set_a.difference_update(set_b)
print(set_a)  # {1, 2, 3}
set_a = {1, 2, 3, 4, 5}  # reset

# Symmetric difference update
set_a.symmetric_difference_update(set_b)
print(set_a)  # {1, 2, 3, 6, 7, 8}
Next: See the complete sets reference table below for a full overview.

7. Set Comprehension

Set comprehensions provide a concise way to create sets.

Basic Syntax

Basics
# Squares of numbers 1-5
squares = {x**2 for x in range(1, 6)}
print(squares)  # {1, 4, 9, 16, 25}

# Unique characters from string
chars = {char for char in "hello world" if char != ' '}
print(chars)  # {'h', 'e', 'l', 'o', 'w', 'r', 'd'}

# Even numbers from range
evens = {x for x in range(10) if x % 2 == 0}
print(evens)  # {0, 2, 4, 6, 8}

Advanced Examples

Filters and primes
# From list with condition
numbers = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4]
unique_evens = {x for x in numbers if x % 2 == 0}
print(unique_evens)  # {2, 4}

# With function calls
def is_prime(n):
    if n < 2:
        return False
    for i in range(2, int(n**0.5) + 1):
        if n % i == 0:
            return False
    return True

primes = {x for x in range(2, 50) if is_prime(x)}
print(primes)  # {2, 3, 5, 7, 11, ...}

# Nested comprehension
cartesian = {(x, y) for x in range(3) for y in range(3)}
print(cartesian)  # {(0, 0), (0, 1), ...}

8. Frozenset

frozenset is an immutable version of set. It can be used as a dictionary key.

Creating Frozensets

frozenset()
# Empty frozenset
empty_frozen = frozenset()

# From iterable
frozen1 = frozenset([1, 2, 3, 3, 4])
print(frozen1)  # frozenset({1, 2, 3, 4})

# From set
regular_set = {1, 2, 3}
frozen2 = frozenset(regular_set)
print(frozen2)  # frozenset({1, 2, 3})

Frozenset Operations

Immutable set algebra
fs1 = frozenset([1, 2, 3, 4])
fs2 = frozenset([3, 4, 5, 6])

# All set operations work (return new frozensets)
print(fs1 | fs2)   # frozenset({1, 2, 3, 4, 5, 6})
print(fs1 & fs2)   # frozenset({3, 4})
print(fs1 - fs2)   # frozenset({1, 2})
print(fs1 ^ fs2)   # frozenset({1, 2, 5, 6})

# Membership testing
print(1 in fs1)    # True

# Can't modify (immutable)
# fs1.add(5)  # AttributeError: 'frozenset' object has no attribute 'add'

# Can be used as dictionary keys
set_dict = {
    frozenset([1, 2]): "value1",
    frozenset([3, 4]): "value2"
}
print(set_dict[frozenset([1, 2])])  # value1

Python Sets Classification

Sets support various operations, methods, and set theory operations. Understanding these features helps you use sets effectively in your programs.

Complete Sets Reference Table

Category Syntax/Keyword Description Example Output
Creation {} / set() Create empty set s = set() set()
Creation {1, 2, 3} Create set with elements s = {1, 2, 3} {1, 2, 3}
Methods add() Add single element s.add(4) Adds 4 to set
Methods remove() Remove element (error if missing) s.remove(3) Removes 3
Methods discard() Remove element (no error) s.discard(3) Removes 3 if present
Methods pop() Remove & return arbitrary element s.pop() Random element
Methods clear() Remove all elements s.clear() set()
Operations | / union() Union of sets a | b Elements in a or b
Operations & / intersection() Intersection of sets a & b Elements in both a and b
Operations - / difference() Difference of sets a - b Elements in a but not b
Operations ^ / symmetric_difference() Symmetric difference a ^ b Elements in a or b but not both
Set Theory issubset() / <= Check if subset a <= b True/False
Set Theory issuperset() / >= Check if superset a >= b True/False
Set Theory isdisjoint() Check if no common elements a.isdisjoint(b) True/False
Quick Tip:
  • Sets are unordered - elements have no index
  • Sets contain unique elements - duplicates automatically removed
  • Sets are mutable but elements must be hashable
  • Use frozenset() for immutable sets (can be dictionary keys)
  • Sets provide O(1) average time for membership tests (in operator)

Sets vs Lists vs Tuples Comparison

Understanding the differences between sets, lists, and tuples helps you choose the right data structure for your needs.

Aspect Sets Unique Lists Mutable Tuples Immutable
Order Unordered Ordered Ordered
Mutability Mutable (except frozenset) Mutable Immutable
Duplicates Not allowed Allowed Allowed
Indexing Not supported Supported (zero-based) Supported (zero-based)
Syntax {} or set() [] ()
Hashable No (frozenset is hashable) No Yes
Use Cases Unique elements, membership tests, set operations Ordered collections, stacks, queues, sequences Immutable sequences, dictionary keys, function returns
Performance O(1) for membership test O(n) for membership test O(n) for membership test
When to Use Each:
  • Use Sets when you need unique elements, fast membership tests, or set operations
  • Use Lists when you need ordered collections that can be modified
  • Use Tuples when you need immutable ordered collections or hashable sequences
  • Use Frozen Sets when you need immutable sets or sets as dictionary keys

Real-World Applications

Sets are used in many practical programming scenarios. Here are common applications:

Removing Duplicates

Quickly remove duplicates from any sequence:

# Remove duplicates from list
numbers = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4]
unique_numbers = list(set(numbers))
print(unique_numbers)  # [1, 2, 3, 4]

# Preserve order (Python 3.7+)
from collections import OrderedDict
ordered_unique = list(OrderedDict.fromkeys(numbers))
Membership Testing

Fast O(1) membership tests:

# Fast keyword checking
keywords = {'if', 'else', 'for', 'while', 'def'}
user_input = "if x > 5: print(x)"

# Check if any keyword in input
has_keyword = any(word in keywords 
                  for word in user_input.split())
print(f"Contains keyword: {has_keyword}")
Set Operations for Data

Find common elements, differences, etc.:

# Social media friends analysis
alice_friends = {'Bob', 'Charlie', 'Diana'}
bob_friends = {'Alice', 'Charlie', 'Eve'}

common = alice_friends & bob_friends
only_alice = alice_friends - bob_friends
all_friends = alice_friends | bob_friends
E-commerce Applications

Product categories, tags, filters:

# Product tags system
product_tags = {
    'laptop': {'electronics', 'computers', 'portable'},
    'book': {'education', 'entertainment'},
    'headphones': {'electronics', 'audio'}
}

# Find all electronic products
electronic_products = [
    product for product, tags in product_tags.items()
    if 'electronics' in tags
]

Key Takeaways

  • Sets store unique, hashable elements with no indexing—use set() for an empty set, not {}
  • Membership and set algebra (union, intersection, difference, symmetric difference) are core strengths
  • frozenset is immutable and can be used as keys or elements where a hashable set is required
  • In-place updates: update, intersection_update, difference_update, symmetric_difference_update
  • Relations: issubset/<=, issuperset/>=, isdisjoint
  • Set comprehensions build sets concisely: {x for x in iterable if cond}