reference
5 min read
·
lesson 5 of 16 in Reference
Python Set Operations Cheat Sheet
1 · The lesson
readUnordered collection of unique, hashable items. O(1) membership tests. Supports mathematical set algebra. For the full tutorial, see Sets.
Creating
python
a = {1, 2, 3} # set literal
b = set() # EMPTY set — NOT {}
c = set([1, 2, 2, 3]) # {1, 2, 3} — dedups
d = set("hello") # {'h','e','l','o'}
e = {x for x in range(5)} # comprehension
f = frozenset([1, 2, 3]) # immutable, hashable
# {} is an EMPTY DICT, not an empty set
type({}) # <class 'dict'>
type(set()) # <class 'set'>Adding & Removing
| Method | Behaviour |
|---|---|
.add(x) | Add single item |
.update(iter) | Add all from iterable (or another set) |
.remove(x) | Remove, raises KeyError if missing |
.discard(x) | Remove if present, no error |
.pop() | Remove & return arbitrary item, KeyError if empty |
.clear() | Empty the set |
python
s = {1, 2}
s.add(3) # {1, 2, 3}
s.update([4, 5]) # {1, 2, 3, 4, 5}
s.update({6}, [7]) # multiple iterables OK
s.remove(99) # KeyError
s.discard(99) # silent
s.pop() # arbitrary itemMembership
python
1 in {1, 2, 3} # True O(1) 4 not in {1, 2, 3} # True
Sets shine when you need fast in tests. Converting a list to a set first is often the win:
python
allowed = set(allowed_list) [x for x in xs if x in allowed] # O(n), not O(n*m)
setup added so this can run · defines allowed_list, xs
# Lightweight mock for objects whose attributes/methods aren't critical class _AutoMock: def __init__(self, name='mock'): self._name = name def __getattr__(self, k): return _AutoMock(self._name + '.' + k) def __call__(self, *a, **kw): print('-> ' + self._name + '() called') return _AutoMock(self._name + '()') def __repr__(self): return '<mock ' + self._name + '>' def __str__(self): return '<mock ' + self._name + '>' def __bool__(self): return True def __iter__(self): return iter([]) def __len__(self): return 0 def __getitem__(self, k): return _AutoMock(self._name + '[...]') def __setitem__(self, k, v): pass def __enter__(self): return self def __exit__(self, *a): return False async def __aenter__(self): return self async def __aexit__(self, *a): return False def __add__(self, o): return self def __radd__(self, o): return self def __sub__(self, o): return self def __mul__(self, o): return self def __rmul__(self, o): return self def __truediv__(self, o): return self def __eq__(self, o): return isinstance(o, _AutoMock) def __hash__(self): return hash(self._name) def __lt__(self, o): return True def __le__(self, o): return True def __gt__(self, o): return False def __ge__(self, o): return False def __mro_entries__(self, bases): return (object,) allowed_list = _AutoMock('allowed_list') xs = ["alpha", "beta", "gamma"]
Set Algebra
| Operator | Method | Meaning |
|---|---|---|
a \| b | a.union(b) | All items in either |
a & b | a.intersection(b) | Items in both |
a - b | a.difference(b) | In a but not b |
a ^ b | a.symmetric_difference(b) | In exactly one |
python
a = {1, 2, 3}
b = {2, 3, 4}
a | b # {1, 2, 3, 4}
a & b # {2, 3}
a - b # {1}
b - a # {4}
a ^ b # {1, 4}Operators (|, &, -, ^) require both sides to be sets. Methods (.union(...), etc.) accept any iterable:
python
{1, 2}.union([3, 4], (5,)) # {1, 2, 3, 4, 5}
{1, 2} | [3, 4] # TypeErrorIn-place Algebra
python
a |= b # a.update(b) union a &= b # a.intersection_update(b) intersect a -= b # a.difference_update(b) subtract a ^= b # a.symmetric_difference_update(b)
setup added so this can run · defines a, b
a = 1 b = 1
Comparisons
| Op | Method | Meaning |
|---|---|---|
a <= b | a.issubset(b) | Every elem of a in b |
a < b | — | Proper subset (a <= b and a != b) |
a >= b | a.issuperset(b) | Every elem of b in a |
a > b | — | Proper superset |
a == b | — | Same elements |
a.isdisjoint(b) | — | No overlap |
python
{1, 2} <= {1, 2, 3} # True
{1, 2} < {1, 2} # False (not proper)
{1, 2}.isdisjoint({3, 4}) # TrueComprehensions
python
{x * 2 for x in range(5)}
{x for x in words if len(x) > 3}
{x.lower() for x in names} setup added so this can run · defines words, names
words = ["alpha", "beta", "gamma"] names = ["alpha", "beta", "gamma"]
Common Patterns
python
# Dedup a list (order NOT preserved) list(set(xs)) # Dedup preserving order (use dict, not set) list(dict.fromkeys(xs)) # Common items between two lists set(a) & set(b) # Items in A not in B set(a) - set(b) # Items unique to either side set(a) ^ set(b) # Fast lookup table banned = {"foo", "bar", "baz"} clean = [w for w in words if w not in banned] # Count unique len(set(xs)) # All unique? len(xs) == len(set(xs)) # frozenset as dict key (sets aren't hashable, frozensets are) groups = {frozenset({1, 2}): "pair_a"}
setup added so this can run · defines xs, a, b, words
# Lightweight mock for objects whose attributes/methods aren't critical class _AutoMock: def __init__(self, name='mock'): self._name = name def __getattr__(self, k): return _AutoMock(self._name + '.' + k) def __call__(self, *a, **kw): print('-> ' + self._name + '() called') return _AutoMock(self._name + '()') def __repr__(self): return '<mock ' + self._name + '>' def __str__(self): return '<mock ' + self._name + '>' def __bool__(self): return True def __iter__(self): return iter([]) def __len__(self): return 0 def __getitem__(self, k): return _AutoMock(self._name + '[...]') def __setitem__(self, k, v): pass def __enter__(self): return self def __exit__(self, *a): return False async def __aenter__(self): return self async def __aexit__(self, *a): return False def __add__(self, o): return self def __radd__(self, o): return self def __sub__(self, o): return self def __mul__(self, o): return self def __rmul__(self, o): return self def __truediv__(self, o): return self def __eq__(self, o): return isinstance(o, _AutoMock) def __hash__(self): return hash(self._name) def __lt__(self, o): return True def __le__(self, o): return True def __gt__(self, o): return False def __ge__(self, o): return False def __mro_entries__(self, bases): return (object,) xs = _AutoMock('xs') a = _AutoMock('a') b = _AutoMock('b') words = ["alpha", "beta", "gamma"]
Common Errors
| Error | Cause | Fix |
|---|---|---|
TypeError: unhashable type: 'list' | Adding list/dict/set to a set | Convert to tuple or frozenset |
{} is dict not set | Empty {} creates a dict | Use set() for empty set |
KeyError on .remove(x) | Item not in set | Use .discard(x) instead |
TypeError: unsupported operand type(s) for & | Mixing set and list with & | Convert: s & set(lst), or use s.intersection(lst) |
| Order seems random | Sets are unordered | Use sorted(s) if you need order |
AttributeError: 'frozenset' object has no attribute 'add' | frozensets are immutable | Use set if you need to mutate |
See Also
Practice this
on practicepython.inShort exercises that run in your browser and tell you what your code actually did, not just whether a test passed.