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

What are Python Sets?

Sets are unordered collections of unique, hashable elements in Python. They are mutable, iterable, and do not allow duplicate values. Sets are ideal for membership testing, removing duplicates, and mathematical set operations.

Key Concept

Sets are unordered and contain only unique elements. They use curly braces {} or the set() constructor. Sets provide O(1) average time complexity for membership tests.

Basic Set Examples
# Creating sets
empty_set = set()  # Note: {} creates empty dict
numbers = {1, 2, 3, 4, 5}
vowels = {'a', 'e', 'i', 'o', 'u'}
mixed = {1, "hello", 3.14, True}

# No duplicates allowed
unique_numbers = {1, 2, 2, 3, 3, 3, 4, 4, 4, 4}
print(unique_numbers)  # {1, 2, 3, 4}

# Set from other sequences
list_to_set = set([1, 2, 3, 2, 1])
string_to_set = set("hello")
tuple_to_set = set((1, 2, 3, 2, 1))

print(f"From list: {list_to_set}")    # {1, 2, 3}
print(f"From string: {string_to_set}") # {'h', 'e', 'l', 'o'}
print(f"From tuple: {tuple_to_set}")  # {1, 2, 3}

# Membership testing
print(f"Is 3 in numbers? {3 in numbers}")  # True
print(f"Is 10 in numbers? {10 in numbers}") # False

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)

Set Examples with Output

Let's explore practical examples of set operations with actual Python code and output.

Set Creation and Basic Methods
# Set Creation and Basic Methods
print("=== Set Creation ===")

# Different ways to create sets
empty_set = set()  # Note: {} creates empty dict
numbers = {1, 2, 3, 4, 5}
vowels = {'a', 'e', 'i', 'o', 'u'}
mixed = {1, "hello", 3.14, True, (1, 2)}  # Note: tuples are hashable

print(f"Empty set: {empty_set}")
print(f"Numbers: {numbers}")
print(f"Vowels: {vowels}")
print(f"Mixed: {mixed}")

# Sets automatically remove duplicates
with_duplicates = {1, 2, 2, 3, 3, 3, 4, 4, 4, 4}
print(f"\nWith duplicates: {with_duplicates}")  # {1, 2, 3, 4}

# From other sequences
list_to_set = set([1, 2, 3, 2, 1])
string_to_set = set("programming")
range_to_set = set(range(5))

print(f"\nFrom list: {list_to_set}")      # {1, 2, 3}
print(f"From string: {string_to_set}")   # {'p', 'r', 'o', 'g', 'a', 'm', 'i', 'n'}
print(f"From range: {range_to_set}")     # {0, 1, 2, 3, 4}

print("\n=== Set Methods ===")
# Creating a set for demonstration
s = {1, 2, 3, 4, 5}
print(f"Original set: {s}")

# add() method
s.add(6)
s.add(2)  # Adding duplicate has no effect
print(f"After add(6), add(2): {s}")

# remove() method
s.remove(3)
print(f"After remove(3): {s}")

# discard() method (safer than remove)
s.discard(4)
s.discard(99)  # No error even though 99 doesn't exist
print(f"After discard(4), discard(99): {s}")

# pop() method (removes arbitrary element)
popped = s.pop()
print(f"After pop(): {s}, popped element: {popped}")

# clear() method
s.clear()
print(f"After clear(): {s}")

print("\n=== Set Operations ===")
# Recreate sets for operations
a = {1, 2, 3, 4, 5}
b = {4, 5, 6, 7, 8}
print(f"Set A: {a}")
print(f"Set B: {b}")

# Length of set
print(f"Length of A: {len(a)}")
print(f"Length of B: {len(b)}")

# Membership test
print(f"\nIs 3 in A? {3 in a}")
print(f"Is 9 in A? {9 in a}")
print(f"Is 4 in B? {4 in b}")

# Iterating through set
print("\nIterating through set A:")
for element in a:
    print(f"  Element: {element}")
Set Operations and Methods
# Set Operations and Methods
print("=== Set Operations ===")

# Create sets for demonstration
a = {1, 2, 3, 4, 5}
b = {4, 5, 6, 7, 8}
c = {2, 3, 4}
print(f"Set A: {a}")
print(f"Set B: {b}")
print(f"Set C: {c}")

# Union (| or union())
union_ab = a | b
union_method = a.union(b)
print(f"\nUnion A | B: {union_ab}")
print(f"Union using method: {union_method}")

# Multiple union
union_abc = a | b | c
print(f"Union A | B | C: {union_abc}")

# Intersection (& or intersection())
intersection_ab = a & b
intersection_method = a.intersection(b)
print(f"\nIntersection A & B: {intersection_ab}")
print(f"Intersection using method: {intersection_method}")

# Difference (- or difference())
difference_ab = a - b
difference_method = a.difference(b)
print(f"\nDifference A - B: {difference_ab}")
print(f"Difference using method: {difference_method}")

# Symmetric Difference (^ or symmetric_difference())
sym_diff_ab = a ^ b
sym_diff_method = a.symmetric_difference(b)
print(f"\nSymmetric Difference A ^ B: {sym_diff_ab}")
print(f"Symmetric Difference using method: {sym_diff_method}")

print("\n=== Update Methods ===")
# Create fresh sets
set1 = {1, 2, 3}
set2 = {3, 4, 5}
set3 = {5, 6, 7}

print(f"Original set1: {set1}")
print(f"Original set2: {set2}")
print(f"Original set3: {set3}")

# update() - adds all elements from other sets
set1.update(set2)
print(f"After set1.update(set2): {set1}")

# intersection_update()
set1 = {1, 2, 3, 4, 5}  # Reset
set1.intersection_update(set2)
print(f"After set1.intersection_update(set2): {set1}")

# difference_update()
set1 = {1, 2, 3, 4, 5}  # Reset
set1.difference_update(set2)
print(f"After set1.difference_update(set2): {set1}")

# symmetric_difference_update()
set1 = {1, 2, 3, 4, 5}  # Reset
set1.symmetric_difference_update(set2)
print(f"After set1.symmetric_difference_update(set2): {set1}")
Set Theory Operations
# Set Theory Operations
print("=== Set Theory Operations ===")

# Create sets for demonstration
a = {1, 2, 3, 4, 5}
b = {2, 3, 4}
c = {6, 7, 8}
d = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

print(f"Set A: {a}")
print(f"Set B: {b}")
print(f"Set C: {c}")
print(f"Set D: {d}")

# Subset check (issubset() or <=)
print(f"\nSubset Checks:")
print(f"Is B subset of A? {b.issubset(a)}")  # True
print(f"Is A subset of B? {a.issubset(b)}")  # False
print(f"B <= A? {b <= a}")  # True (same as issubset)
print(f"A <= D? {a <= d}")  # True

# Proper subset check (<)
print(f"\nProper Subset Checks:")
print(f"B < A? {b < a}")  # True (B is proper subset of A)
print(f"A < A? {a < a}")  # False (not proper subset of itself)
print(f"A < D? {a < d}")  # True

# Superset check (issuperset() or >=)
print(f"\nSuperset Checks:")
print(f"Is A superset of B? {a.issuperset(b)}")  # True
print(f"Is B superset of A? {b.issuperset(a)}")  # False
print(f"D >= A? {d >= a}")  # True (same as issuperset)

# Proper superset check (>)
print(f"\nProper Superset Checks:")
print(f"A > B? {a > b}")  # True
print(f"A > A? {a > a}")  # False
print(f"D > A? {d > a}")  # True

# Disjoint check (isdisjoint())
print(f"\nDisjoint Checks:")
print(f"Are A and C disjoint? {a.isdisjoint(c)}")  # True
print(f"Are A and B disjoint? {a.isdisjoint(b)}")  # False
print(f"Are B and C disjoint? {b.isdisjoint(c)}")  # True

print("\n=== Copying Sets ===")
# Shallow copy
original = {1, 2, 3, 4, 5}
shallow_copy = original.copy()
print(f"Original: {original}")
print(f"Shallow copy: {shallow_copy}")

# Modifying copy doesn't affect original
shallow_copy.add(6)
print(f"After adding to copy:")
print(f"  Original: {original}")
print(f"  Copy: {shallow_copy}")

# Set comprehension
print("\n=== Set Comprehensions ===")
# Create set of squares
squares = {x**2 for x in range(10)}
print(f"Squares of 0-9: {squares}")

# Create set of even numbers
evens = {x for x in range(20) if x % 2 == 0}
print(f"Even numbers 0-19: {evens}")

# Create set from string with condition
unique_vowels = {char for char in 'hello world' if char in 'aeiou'}
print(f"Unique vowels in 'hello world': {unique_vowels}")

Set Theory Visualization

Understanding set theory operations is easier with visual representations. Here are the main set operations visualized.

Venn Diagram: Set Operations

Set A
{1, 2, 3, 4}
Set B
{3, 4, 5, 6}
Intersection
{3, 4}
Union A ∪ B
A | B

{1, 2, 3, 4, 5, 6}

Intersection A ∩ B
A & B

{3, 4}

Difference A - B
A - B

{1, 2}

Symmetric Difference
A ^ B

{1, 2, 5, 6}

Set Theory Implementation
# Set Theory Implementation Example
print("=== Set Theory Implementation ===")

# Define sets
A = {1, 2, 3, 4, 5}
B = {4, 5, 6, 7, 8}
C = {2, 3, 4}
U = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}  # Universal set

print(f"Set A: {A}")
print(f"Set B: {B}")
print(f"Set C: {C}")
print(f"Universal Set U: {U}")

# Basic set theory operations
print(f"\nBasic Operations:")
print(f"A ∪ B (Union): {A | B}")
print(f"A ∩ B (Intersection): {A & B}")
print(f"A - B (Difference): {A - B}")
print(f"B - A (Difference): {B - A}")
print(f"A △ B (Symmetric Difference): {A ^ B}")

# Complement (relative to universal set)
complement_A = U - A
complement_B = U - B
print(f"\nComplement of A (relative to U): {complement_A}")
print(f"Complement of B (relative to U): {complement_B}")

# De Morgan's Laws
print(f"\nDe Morgan's Laws Verification:")
# First Law: (A ∪ B)' = A' ∩ B'
left_side = U - (A | B)
right_side = (U - A) & (U - B)
print(f"(A ∪ B)' = {left_side}")
print(f"A' ∩ B' = {right_side}")
print(f"Law holds: {left_side == right_side}")

# Second Law: (A ∩ B)' = A' ∪ B'
left_side = U - (A & B)
right_side = (U - A) | (U - B)
print(f"\n(A ∩ B)' = {left_side}")
print(f"A' ∪ B' = {right_side}")
print(f"Law holds: {left_side == right_side}")

# Distributive Laws
print(f"\nDistributive Laws Verification:")
# A ∪ (B ∩ C) = (A ∪ B) ∩ (A ∪ C)
left_side = A | (B & C)
right_side = (A | B) & (A | C)
print(f"A ∪ (B ∩ C) = {left_side}")
print(f"(A ∪ B) ∩ (A ∪ C) = {right_side}")
print(f"Law holds: {left_side == right_side}")

# A ∩ (B ∪ C) = (A ∩ B) ∪ (A ∩ C)
left_side = A & (B | C)
right_side = (A & B) | (A & C)
print(f"\nA ∩ (B ∪ C) = {left_side}")
print(f"(A ∩ B) ∪ (A ∩ C) = {right_side}")
print(f"Law holds: {left_side == right_side}")

Frozen Sets

Frozen sets are immutable versions of sets. Once created, they cannot be modified, making them hashable and suitable for use as dictionary keys or elements in other sets.

Frozen Set Examples
# Frozen Set Examples
print("=== Frozen Sets ===")

# Creating frozen sets
fs1 = frozenset([1, 2, 3, 4, 5])
fs2 = frozenset({4, 5, 6, 7, 8})
fs3 = frozenset("hello")

print(f"Frozen set 1: {fs1}")
print(f"Frozen set 2: {fs2}")
print(f"Frozen set 3: {fs3}")

# Frozen sets support set operations (return new frozen sets)
print(f"\nSet Operations with Frozen Sets:")
print(f"Union: {fs1 | fs2}")
print(f"Intersection: {fs1 & fs2}")
print(f"Difference: {fs1 - fs2}")
print(f"Symmetric Difference: {fs1 ^ fs2}")

# Frozen sets are hashable (can be dictionary keys)
print(f"\nUsing Frozen Sets as Dictionary Keys:")
# Create dictionary with frozen set keys
configurations = {
    frozenset(['server', 'database']): "Production config",
    frozenset(['server', 'cache']): "Caching config",
    frozenset(['database', 'cache']): "Storage config"
}

for key, value in configurations.items():
    print(f"  {set(key)}: {value}")

# Frozen sets can be elements in other sets
print(f"\nFrozen Sets as Set Elements:")
set_of_frozensets = {
    frozenset([1, 2, 3]),
    frozenset([4, 5, 6]),
    frozenset([7, 8, 9])
}
print(f"Set of frozen sets: {set_of_frozensets}")

# Try to modify frozen set (will raise error)
try:
    fs1.add(6)  # AttributeError
    print("This won't print")
except AttributeError as e:
    print(f"\nCannot modify frozen set: {e}")

try:
    fs1.remove(1)  # AttributeError
    print("This won't print")
except AttributeError as e:
    print(f"Cannot remove from frozen set: {e}")

# Methods available on frozen sets
print(f"\nMethods available on frozen sets:")
print(f"fs1.issubset(fs2): {fs1.issubset(fs2)}")
print(f"fs1.issuperset(fs2): {fs1.issuperset(fs2)}")
print(f"fs1.isdisjoint(fs2): {fs1.isdisjoint(fs2)}")
print(f"Length: {len(fs1)}")
print(f"Membership: {3 in fs1}")
print(f"Iteration: ", end="")
for item in fs1:
    print(item, end=" ")
When to Use Frozen Sets:
  • When you need immutable sets (cannot be changed after creation)
  • As dictionary keys (regular sets are not hashable)
  • As elements in other sets (regular sets cannot be in sets)
  • When you want to ensure the set remains constant
  • For configuration data, constants, or fixed collections

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
]

Practice Exercises

Test your set skills with these exercises. Try to solve them before looking at solutions.

Set Exercises
# Python Sets Practice Exercises

print("=== Exercise 1: Basic Set Operations ===")
# Create sets and perform basic operations
A = {1, 2, 3, 4, 5}
B = {4, 5, 6, 7, 8}
print(f"Set A: {A}")
print(f"Set B: {B}")
print(f"Union: {A | B}")
print(f"Intersection: {A & B}")
print(f"Difference A-B: {A - B}")
print(f"Difference B-A: {B - A}")
print(f"Symmetric Difference: {A ^ B}")

print("\n=== Exercise 2: Remove Duplicates ===")
# Remove duplicates from list using set
numbers = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5]
unique_numbers = list(set(numbers))
print(f"Original list: {numbers}")
print(f"Unique numbers: {unique_numbers}")

print("\n=== Exercise 3: Set Comprehensions ===")
# Create sets using comprehensions
# Squares of even numbers 0-9
even_squares = {x**2 for x in range(10) if x % 2 == 0}
print(f"Even squares 0-9: {even_squares}")

# Unique characters from string
text = "hello world python programming"
unique_chars = {char for char in text if char != ' '}
print(f"Unique chars in text: {unique_chars}")

print("\n=== Exercise 4: Set Methods ===")
# Practice set methods
s = {1, 2, 3, 4, 5}
print(f"Original set: {s}")

s.add(6)
print(f"After add(6): {s}")

s.remove(3)
print(f"After remove(3): {s}")

s.discard(10)  # No error
print(f"After discard(10): {s}")

popped = s.pop()
print(f"After pop(): {s}, popped: {popped}")

print("\n=== Exercise 5: Set Theory ===")
# Verify set theory properties
U = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}  # Universal set
X = {1, 2, 3, 4, 5}
Y = {4, 5, 6, 7, 8}

print(f"Universal set U: {U}")
print(f"Set X: {X}")
print(f"Set Y: {Y}")

# Complement
X_complement = U - X
Y_complement = U - Y
print(f"\nComplement of X: {X_complement}")
print(f"Complement of Y: {Y_complement}")

# De Morgan's Law: (X ∪ Y)' = X' ∩ Y'
left = U - (X | Y)
right = X_complement & Y_complement
print(f"\n(X ∪ Y)': {left}")
print(f"X' ∩ Y': {right}")
print(f"De Morgan's Law holds: {left == right}")

print("\n=== Exercise 6: Real-world Application ===")
# Course enrollment system
math_students = {'Alice', 'Bob', 'Charlie', 'Diana'}
physics_students = {'Bob', 'Diana', 'Eve', 'Frank'}

print(f"Math students: {math_students}")
print(f"Physics students: {physics_students}")

# Students in both courses
both_courses = math_students & physics_students
print(f"Students in both courses: {both_courses}")

# Students in only one course
only_one = math_students ^ physics_students
print(f"Students in only one course: {only_one}")

# All students
all_students = math_students | physics_students
print(f"All students: {all_students}")

print("\n=== Exercise 7: Frozen Sets ===")
# Create and use frozen sets
fs1 = frozenset([1, 2, 3])
fs2 = frozenset([3, 4, 5])
print(f"Frozen set 1: {fs1}")
print(f"Frozen set 2: {fs2}")
print(f"Union: {fs1 | fs2}")
print(f"Intersection: {fs1 & fs2}")

# Frozen set as dictionary key
config = {
    frozenset(['debug', 'verbose']): "Development mode",
    frozenset(['production', 'secure']): "Production mode"
}
print(f"\nConfigurations: {config}")

Advanced Set Techniques

Set Comprehensions
# Advanced set comprehensions
# Set of prime numbers < 50
primes = {x for x in range(2, 50) 
          if all(x % y != 0 
                 for y in range(2, int(x**0.5)+1))}
print(f"Primes < 50: {primes}")

# Set of Pythagorean triples < 20
triples = {(a, b, c) 
           for a in range(1, 20)
           for b in range(a, 20)
           for c in range(b, 20)
           if a*a + b*b == c*c}
print(f"Pythagorean triples: {triples}")
Symmetric Operations
# Advanced symmetric operations
# Find elements unique to each set
set1 = {1, 2, 3, 4, 5}
set2 = {4, 5, 6, 7, 8}
set3 = {3, 4, 5, 9, 10}

# Elements in exactly one set
unique_to_one = set1 ^ set2 ^ set3 ^ (
    set1 & set2 & set3)
print(f"Unique to one set: {unique_to_one}")

# Elements in at least two sets
in_at_least_two = (
    (set1 & set2) | 
    (set1 & set3) | 
    (set2 & set3))
print(f"In at least two sets: {in_at_least_two}")
Set Partitioning
# Partition sets based on conditions
numbers = set(range(1, 21))

# Partition into even and odd
even = {x for x in numbers if x % 2 == 0}
odd = {x for x in numbers if x % 2 != 0}

# Partition into multiples
multiples_of_3 = {x for x in numbers if x % 3 == 0}
multiples_of_5 = {x for x in numbers if x % 5 == 0}

print(f"Even: {even}")
print(f"Odd: {odd}")
print(f"Multiples of 3: {multiples_of_3}")
print(f"Multiples of 5: {multiples_of_5}")
Performance Optimization
# Using sets for performance
# Slow with lists (O(n) for each check)
def slow_find_common(list1, list2):
    return [x for x in list1 if x in list2]

# Fast with sets (O(1) for lookup)
def fast_find_common(list1, list2):
    set2 = set(list2)
    return [x for x in list1 if x in set2]

# Example
large_list1 = list(range(10000))
large_list2 = list(range(5000, 15000))

# Set approach is much faster
common = fast_find_common(large_list1, large_list2)
print(f"Common elements: {len(common)}")

Key Takeaways

  • Sets are unordered collections of unique elements: {item1, item2, item3}
  • Use set() for empty set (not {} which creates empty dict)
  • Sets automatically remove duplicates - great for deduplication
  • Sets provide O(1) average time for membership tests (in operator)
  • Main set operations: Union (|), Intersection (&), Difference (-), Symmetric Difference (^)
  • Set methods: add(), remove(), clear(), update(), intersection_update(), etc.
  • Frozen sets (frozenset()) are immutable and hashable (can be dictionary keys)
  • Set elements must be hashable - no lists or dictionaries as set elements
  • Sets support set comprehensions: {x**2 for x in range(10)}
  • Use sets for: removing duplicates, membership testing, mathematical set operations
  • Sets are unordered - cannot index or slice them
  • Set theory operations: issubset(), issuperset(), isdisjoint()
  • Sets can contain mixed types but all elements must be hashable
  • Sets are faster than lists/tuples for membership testing but slower for iteration