The first time I saw all four Python containers listed on one slide — list, tuple, set, dict — I assumed three of them were for other people. Six months of small scripts later the pattern was obvious: each one answers a different question, and picking the right one at the start makes the code around it fall into place.
ordered? changeable? duplicates?
list yes yes yes
tuple yes no yes
set no yes no
dict yes yes keys: no
(Dicts have kept their insertion order in every Python since 3.7 — old enough to rely on.) So the real questions are: do I care about order, will the contents change, can things appear twice, and do I need to reach items by name rather than by position?
todos = ["buy milk", "write post", "buy milk"]
todos.append("ship it") # three items become four
todos[0] # 'buy milk' — counting starts at 0
Ordered, changeable, duplicates welcome. This is the container for anything you'd write on a whiteboard: a queue of jobs, the rows of a CSV, the folders to back up. When nothing fancier is asking for the job, a list is rarely wrong.
point = (48.8584, 2.2945) # the Eiffel Tower, as floats
point.append(0.0)
# AttributeError: 'tuple' object has no attribute 'append'
Same square-bracket indexing, but no changing. That sounds like a limitation and is really a promise: tuples are for fixed shapes — coordinates, RGB colors, the two values a function hands back with return x, y. When changing a value would be a bug, a tuple makes the bug impossible instead of likely.
tags = {"python", "blog", "python"}
len(tags) # 2 — the second 'python' is gone
"python" in tags # True — and this check stays fast
No order, no duplicates, membership checks that stay quick even on big collections. My most common set move: set(rows) to strip the duplicates out of something I just read from a file. That's it, and it's worth the whole container.
user = {"name": "Ada", "lang": "en"}
user["name"] # 'Ada'
user.get("age") # None — key missing, but no crash
The container for anything with a natural label: settings, one record per id, counts per word. Where a list answers "what's third?", a dict answers "what's the email for user 4171?" — and it does it without scanning the whole collection.
Real data rarely stays one flat container. A CSV import lands as a list of dicts, one per row; a word count is a dict whose values are numbers; my backups script walks a dict of folders, each holding a list of files. The card above still applies — you just read it from the inside out: what is each item, and then what is the collection of them? That question has picked the right container for me every time.
Which ones do I actually reach for? list and dict, easily ten to one over the rest. Tuples show up whether I invite them or not — every function that returns two things hands me one — and sets earn their keep on deduplication days. If you're new and four containers feel like a lot: learn list and dict properly and you're equipped for most scripts. The other two will introduce themselves.