5.13 Choosing the Right Data Type
How to pick the right Python data type for a given piece of data based on performance and memory, with a real-world selection table.
Picking the right type up front avoids both bugs and performance problems later — three questions to ask for any given piece of data.
Performance
What Is It?
Different types have very different costs for the same logical operation.
Why Does It Matter?
Checking membership (x in collection) is O(n) on a list but O(1) average on a set — for a large collection checked repeatedly, that’s the difference between a script that’s instant and one that’s noticeably slow.
# Slow for large lists: O(n) per lookup
blocked_ips = ["10.0.0.1", "10.0.0.2", ...] # imagine thousands of entries
if user_ip in blocked_ips:
deny_access()
# Fast: O(1) average per lookup
blocked_ips = {"10.0.0.1", "10.0.0.2", ...} # a set instead
if user_ip in blocked_ips:
deny_access()
Memory
A tuple generally uses less memory than an equivalent list (no room reserved for future growth), and a range() uses almost none regardless of how large the range is, since it never materializes the full sequence (see 5.4 Sequence Data Types).
Real-World Selection
| Situation | Best Type |
|---|---|
| Fixed collection of settings that shouldn’t change | tuple |
| Growing/shrinking list of items | list |
| Need fast “have I seen this before?” checks | set |
| Labeled/structured data (like a JSON object) | dict |
| Large range of numbers to iterate, not store | range |
| Raw file or network data | bytes / bytearray |
Quick Interview Answer
“Choosing a data type comes down to performance, memory, and what the data actually represents. Membership testing is O(n) on a list but O(1) average on a set, so a set wins for repeated ‘have I seen this?’ checks. A tuple uses less memory than an equivalent list and signals ’this won’t change.’
range()never materializes its full sequence, so it’s nearly free memory-wise even for huge ranges.”
Common Mistakes
- Defaulting to
listfor everything, including cases where aset(fast membership) ortuple(fixed, hashable record) is the actually correct choice. - Materializing a large
range()into alistwhen the lazyrangeitself would have worked fine for iteration.
Add More Questions to This Guide
Know a question that should be here? Share it and help the community!
Open Google Form