Python

Lists, tuples, dicts, and sets — the basics

The four built-in collection types you'll reach for constantly, what makes each one actually different from the others, and which one fits which job.

Beginner

4 min read

Why there are four different collection types, not just one

Every one of these holds multiple values, but each makes a different trade-off about order, uniqueness, and how values are looked up — picking the right one isn't a style preference, it's about matching the structure to what the data actually needs to do.

List: an ordered, changeable sequence

fruits = ["apple", "banana", "cherry"]
fruits.append("date")          # ["apple", "banana", "cherry", "date"]
fruits[0] = "avocado"           # ["avocado", "banana", "cherry", "date"]
fruits.remove("banana")         # ["avocado", "cherry", "date"]

A list keeps its items in a specific order (the order you put them in, or however you later sort them), and it's mutable — you can add, remove, or change elements after creating it. This is the default, general-purpose collection: reach for a list whenever you need an ordered group of items that might change over time. Lists can hold duplicate values (["a", "a", "b"] is perfectly valid) and mixed types, though in practice most lists hold one consistent kind of thing.

Tuple: an ordered, unchangeable sequence

point = (3, 4)
point[0]        # 3
point[0] = 5    # TypeError: 'tuple' object does not support item assignment

A tuple is ordered like a list, but immutable — once created, it can't be changed. This isn't a missing feature; it's the point. A tuple is the right choice when a fixed, small group of values genuinely shouldn't change after creation — coordinates (x, y), an RGB color (255, 0, 0), or any "this is a fixed bundle of related values" situation. Immutability also means a tuple can be used as a dictionary key (covered below) or stored in a set, which a list can never do, precisely because lists can change after being added.

Dict: key-value pairs, looked up by key

person = {"name": "Ada", "age": 25}
person["name"]              # "Ada"
person["email"] = "ada@example.com"    # add a new key
"age" in person               # True — checks keys, not values
person.get("phone", "N/A")   # "N/A" — safe lookup with a default if missing

A dict (dictionary) stores values indexed by a key instead of a numeric position — person["name"] looks up by the key "name", not by position 0. This is the right structure whenever data is naturally described as "this specific thing maps to that value" — a username to a user record, a product ID to its price, a word to its definition. dict["missing_key"] raises a KeyError if the key doesn't exist; .get(key, default) avoids the crash by returning a fallback value instead, which is almost always what you actually want when a missing key is a normal, expected possibility rather than a bug.

Set: unique values, no order, fast membership checks

tags = {"python", "web", "python", "beginner"}
tags                    # {"python", "web", "beginner"} — the duplicate is gone automatically
"web" in tags            # True — very fast, regardless of set size
tags.add("api")
tags.remove("web")

A set stores unique values with no guaranteed order — adding "python" twice results in it appearing only once, automatically, since a set can't hold duplicates by definition. Its real advantage is speed: checking x in tags is fast (close to O(1)) regardless of how large the set is, unlike checking x in some_list, which has to scan every element (O(n)). Reach for a set specifically when you need "does this exist" checks to be fast, or when you need to automatically deduplicate a collection of values.

Picking the right one: a quick decision guide

Real code often combines them — a list of dicts ([{"name": "Ada"}, {"name": "Grace"}]) representing a table of records, or a dict whose values are lists ({"fruits": ["apple", "banana"]}) grouping items under keys — nesting these four building blocks is how most real-world data actually gets represented in Python before it touches a database or an API.

Further reading

Check your understanding

A quick comprehension check — not tracked, not graded, just for you.

1. Which of these can be used as a Python dictionary key?

2. What happens if you add the same value to a Python set twice?

3. Why is `x in my_set` generally much faster than `x in my_list` for a large collection?

4. What does `person.get("phone", "N/A")` do if `"phone"` isn't a key in `person`?