When should you use a list, tuple, set, or dict?

5 minbeginnercollectionslisttuplesetdict

Quick Answer

List: ordered, mutable, allows duplicates. A general-purpose sequence. Tuple: ordered, immutable. Fixed-size records, safe as a dict key/set element. Set: unordered, unique elements, O(1) membership testing. Good for deduplication and fast "contains" checks. Dict: key→value mapping, O(1) lookup by key, insertion-ordered. The default choice whenever you need to look things up by a name/id rather than by position.

Detailed Answer

Quick decision table

NeedStructureWhy
Ordered, mutable collection, duplicates OKlistgeneral-purpose sequence
Fixed-size, immutable record ((x, y), (name, age))tuplesafe to hash, signals "this won't change"
Fast membership testing, deduplicationsetO(1) average in, automatic uniqueness
Lookup by key/namedictO(1) average lookup by key, not position

Concrete examples

# list -- ordered sequence of items, order and duplicates matter
scores = [85, 92, 85, 78]

# tuple -- an immutable, fixed-shape record
point = (3, 4)
person = ("Ada", 36)

# set -- membership and uniqueness, order doesn't matter
seen_ids = {101, 205, 310}
if user_id in seen_ids:   # O(1) average -- much faster than `in a_list` for large data
    ...
unique_tags = set(all_tags)  # dedupe in one line

# dict -- look things up by key
users_by_id = {101: "Ada", 205: "Grace"}
users_by_id[101]   # O(1) average

Why x in set beats x in list at scale

big_list = list(range(1_000_000))
big_set = set(big_list)

999_999 in big_list   # O(n) -- scans up to a million elements
999_999 in big_set     # O(1) average -- direct hash lookup

For any workload doing repeated membership checks against a large collection, converting to a set (or using a dict if you also need associated values) is one of the cheapest, highest-impact optimizations available.

Tuple vs list: signaling intent, not just performance

def get_coordinates():
    return (self.x, self.y)   # a tuple signals "this is a fixed 2-item record"

Beyond being hashable (usable as dict keys/set elements) and slightly more memory-efficient, using a tuple for a fixed-shape value communicates to readers that the shape, not just the values, is meant to be fixed. Nobody should expect to .append() to it.

Reach for list for ordered, mutable sequences; tuple for fixed-shape, immutable records (and anything you need to hash); set for uniqueness/fast membership testing; dict whenever you look things up by key rather than by position. The performance difference between O(n) list scans and O(1) set/dict lookups is often the single biggest algorithmic win available in everyday code.