Python Data Structures
Theme
Palette
Download
Caption (tap to copy)
📖 Deep dive (full written explanation)
This post opens the topic by reframing data structures as decisions rather than syntax. Most beginners learn list and dict as 'the brackets you type' without ever asking why four different containers exist. The cover sets up the real claim of the day: the container you pick is a performance and correctness decision that ripples through everything built on top of it.
The goal of post one is purely definitional. Before you can reason about speed or pick the right tool, you need a crisp mental model of what each of the four built-ins actually is and what promise it makes.
A data structure is the arrangement of values in memory plus the operations that arrangement makes cheap. That second half is the part people skip. Every structure is a trade: optimize for fast lookup and you give up ordered insertion cost, optimize for ordered growth and you give up instant membership. There is no universally best container.
Python's design choice was to ship four general-purpose ones that cover the overwhelming majority of everyday needs, so you rarely have to implement your own. Understanding what each optimizes for is the whole game.
The list is the container people reach for first, and usually correctly. It is an ordered, mutable sequence: items stay in the order you put them, and you can append, insert, sort, and remove freely. The square-bracket literal is so common it becomes invisible.
The key mental tag for a list is 'an editable pile where order matters.' If you find yourself caring about position, or the collection grows and shrinks over its life, a list is almost always right. Its weakness — slow membership checks — is the subject of the next post.
A tuple is the list's frozen sibling: same ordered-sequence idea, but immutable. Once you create (10, 20) you cannot reassign, append, or delete from it. That rigidity is the feature, not a limitation.
Use tuples for fixed-shape records — a coordinate, an RGB triple, a row returned from a function — where the number and meaning of fields should never change. Because they're immutable they're also hashable, which is why a tuple can be a dict key but a list cannot. That single property quietly makes tuples essential later.
A dict maps unique keys to values, and it is arguably the most important container in Python — the language itself is built on dicts internally. Instead of accessing by position, you access by a meaningful key, and that lookup is near-instant regardless of how many entries exist.
The mental tag is 'named data with fast lookup.' Whenever your data has labels — a user's fields, a config's settings, a count per category — a dict expresses it directly. The next post shows why that lookup speed is the headline feature.
A set is an unordered collection of unique values. Adding a duplicate is a silent no-op, which makes deduplication trivial. Like dicts, sets are backed by a hash table, so membership testing is fast rather than a linear scan.
The mental tag is 'uniqueness and fast membership.' If your core question is 'have I seen this before?' or 'what's unique across these?', a set answers it directly and efficiently. The cost is that sets carry no order and hold no associated values — they're pure membership.
This code slide grounds the four definitions in one runnable block so the literal syntax is unmistakable: square brackets for list, parentheses for tuple, curly braces with colons for dict, and curly braces of bare values for set. Printing each type confirms what Python actually created.
The deliberate detail is the duplicate 2 in the list versus the unique values in the set — a preview that the set would collapse duplicates. Seeing all four declared side by side builds the comparison the rest of the day relies on.
The mutable-versus-immutable axis is the single most useful lens for organizing these containers. Lists, dicts, and sets can be changed in place; tuples, strings, and frozensets cannot. This isn't pedantry — mutability decides whether an object can be a dict key, whether it's safe to share across functions, and whether 'b = a' is a trap.
The comparison slide deliberately includes str and frozenset alongside tuple so you see immutability is a property, not a single type. Internalizing this axis prevents a whole category of bugs covered on day five.
The mindmap turns the four definitions into a decision tool. Rather than memorizing properties, you answer one question — what do I need to do with this data? — and the branch points you at the container. Ordered and changeable leads to list; ordered and fixed leads to tuple; lookup by key leads to dict; uniqueness leads to set.
This question-first framing is how experienced developers actually choose. They don't recite Big-O tables; they map the requirement to the structure whose guarantee matches, and the performance follows automatically.
The cheat sheet compresses the whole post into five lines you can recall instantly. Each line pairs the container with its defining tradeoff so the tag does the remembering for you. The final bullet — that strings behave like immutable sequences of characters — bridges to a useful realization: slicing and indexing you learn on lists transfer directly to strings.
Keeping this list in working memory is enough to make correct first-guess container choices the norm rather than something you reason out each time.
The closing mistake names the failure mode this whole post exists to prevent: defaulting to a list for everything. It works, so it never throws an error, which is exactly why it persists. The cost shows up later as slow membership checks, awkward by-name lookups faked with parallel lists, and duplicate bugs.
The fix is the habit the post teaches: treat the container as a deliberate choice driven by one question about access pattern and uniqueness. That single question, asked up front, picks the right structure almost every time.
The CTA closes post one and points forward. Having defined the four containers and the two axes that distinguish them, the natural next question is 'why does this actually matter in practice?' That's exactly what post two answers, moving from definitions to the concrete performance and correctness payoffs.