Sets: operations and use cases

RoadmapsPython

Overview

A `set` is an unordered collection of unique, hashable (having a hash value which never changes during its lifetime) elements. It is defined using curly braces `{1, 2, 3}` or the `set()` constructor. Unlike a `list`, a `set` automatically discards duplicate values and cannot be accessed by index. Think of a `set` like a VIP guest list: someone is either on the list or they aren't, but their exact position in line doesn't matter (unordered). Because sets are backed by a hash table, membership checks (`x in myset`) execute in `O(1)` time. This makes them significantly faster than scanning a `list` in `O(n)` time. Sets support powerful mathematical operations for comparing collections: - `|` (Union): Returns a new `set` containing all unique elements from both sets. - `&` (Intersection): Returns a new `set` containing only elements present in both sets. - `-` (Difference): Returns a new `set` containing elements in the first set but not the second. When removing elements, you must choose how to handle missing values. Sets provide two distinct methods: - `remove(x)`: Removes `x` from the `set`. Returns `None`. Raises a `KeyError` if `x` is missing. - `discard(x)`: Removes `x` from the `set` if present. Returns `None`. Never raises an exception if `x` is missing. This presents a common edge case where `remove()` crashes on missing elements: active_users = {"alice", "bob"} active_users.remove("charlie") # KeyError: 'charlie' active_users.discard("charlie") # Does nothing, succeeds Sets only accept hashable objects, meaning you cannot store mutable types like a `list` or `dict`: invalid_set = {[1, 2], [3, 4]} # TypeError: unhashable type: 'list' The relationship between mutability and hashing is covered fully in `collection-complexity`. Another dangerous edge case is attempting to modify a `set` while iterating over it. This will immediately crash your program: active_users = {"alice", "bob", "charlie"} for user in active_users: if user == "bob": active_users.remove(user) # RuntimeError: Set changed size during iteration To safely remove items during iteration, you must iterate over a copy of the collection instead.

Sets are optimized for two things: answering whether an item is in the collection instantly, and guaranteeing uniqueness. When you need to check if a user has a specific permission out of thousands, a `set` makes that check extremely fast compared to scanning a `list`.

Where used: API scope validation, Deduplicating database rows, Feature flags

Why learn this

Code walkthrough

user_roles = ['user', 'admin', 'user']
unique_roles = set(user_roles)
print(unique_roles)

Focus: Notice how passing the `list` into `set()` instantly strips out the duplicate `'user'` entry.

Common mistakes

Glossary

unordered collection
A group of items that do not have a specific sequence or position, meaning you can't rely on their order. Example: `{3, 1, 2}`.
deduplicating
The process of removing duplicate or repeated items from a dataset so that only unique items remain. Example: `set([1, 1, 2])` gives `{1, 2}`.

Recall questions

Understanding checks

What is the output of this code?

2

Sets automatically discard duplicate values. The resulting `set` is `{'user', 'admin'}`.

A developer writes `empty_set = {}` to initialize an empty `set`. Why is this incorrect?

Because `{}` creates an empty `dict`, not an empty `set`.

Python uses `{}` for `dict`ionaries. To create an empty `set`, you must explicitly use the `set()` constructor.

Practice tasks

Find missing scopes

The `get_missing_scopes` function takes two `list`s of `str`s. Modify it to return a `set` of scopes that are in `required_scopes` but NOT in `user_scopes`.

Challenge

Validate user permissions

You are building an API middleware that checks if a user has access to an endpoint. Write a function `has_access(user_roles, required_roles)` that takes two iterables. Return `True` if the user has ALL of the required roles, and `False` otherwise. Additionally, verify you don't use `list` operations.

Continue learning

Previous: Primitive types: int, float, bool, str

Previous: Mutable vs immutable objects

Previous: Lists: indexing, slicing, methods

Next: Time Complexity of Collection Operations

Next: Dictionary and set comprehensions

Return to Python Roadmap