ScreenshotNeo

BlogGuides

Python Data Structures Explained With Examples

Learn when to use Python lists, tuples, sets, dictionaries, and queues with clear examples, selection rules, pitfalls, and runnable code.

By the ScreenshotNeo team1 October 20267 min read

Python’s built-in data structures let you store, organize, and retrieve values. The main choices are list, tuple, set, dict, and, for queue workflows, collections.deque.

Choose based on five questions:

  • Does order matter?
  • Will the collection change after creation?
  • Are duplicate values allowed?
  • Do you retrieve by position, membership, or a meaningful key?
  • Do you need first-in, first-out processing?
Structure Mental model Use it when Watch for
list Mutable ordered sequence Items need order, indexing, slicing, or updates Front insertion/removal is inefficient for queues
tuple Fixed sequence of grouped values A group’s slots should not be reassigned It may still contain mutable objects
set Unordered unique elements Deduplication, membership, and set algebra Do not rely on display order
dict Unique keys mapped to values Lookup by a meaningful key Keys must be hashable
collections.deque Double-ended queue FIFO or fast operations at both ends It is a standard-library type, not a literal

1. Lists: ordered, mutable sequences

A list keeps items in sequence order and can be changed in place. You can index, slice, append, remove, sort, and iterate over it.

scores = [8, 10, 9]
scores.append(7)
print(scores)       # [8, 10, 9, 7]
print(scores[0])    # 8
print(scores[1:3]) # [10, 9]

scores[0] = 11
last = scores.pop()
print(last)         # 7
print(scores)       # [11, 10, 9]

List comprehensions

A comprehension creates a list from an iterable, optionally filtering values.

numbers = [1, 2, 3, 4, 5]
squares = [n * n for n in numbers]
even_squares = [n * n for n in numbers if n % 2 == 0]

print(squares)       # [1, 4, 9, 16, 25]
print(even_squares)  # [4, 16]

Common list mistakes

  • append(value) adds one item; extend(iterable) adds each item from an iterable.
  • remove(value) removes the first matching value and raises ValueError if none exists.
  • Indexing outside the list raises IndexError.
  • Copy a list with items.copy() or items[:] when you need a separate outer list.

2. Tuples: fixed-position groups

A tuple is a sequence whose individual slots cannot be reassigned. Tuples are useful for records or values that belong together, such as coordinates.

point = (3, 5)
x, y = point
print(x, y)  # 3 5

# Packing
color = 255, 128, 0

# Unpacking with a starred target
first, *middle, last = (1, 2, 3, 4)
print(first, middle, last)  # 1 [2, 3] 4

The immutability applies to the tuple’s slots. A tuple can contain a mutable object, so the object inside may still change.

record = ("job-7", ["queued"])
record[1].append("started")
print(record)  # ('job-7', ['queued', 'started'])

# This reassignment is invalid:
# record[0] = "job-8"  # TypeError

Use a one-item tuple with a trailing comma: single = ("value",). Parentheses alone do not create the tuple.

3. Sets: unique values and membership

A set contains unique elements and is unordered. It is a good fit for removing duplicates, checking membership, and comparing groups.

seen = {"red", "blue", "red"}
print(seen)           # {'red', 'blue'} in some order
print("blue" in seen) # True

seen.add("green")
seen.discard("red")

left = {"a", "b", "c"}
right = {"b", "c", "d"}
print(left | right)  # union
print(left & right)  # intersection
print(left - right)  # difference
print(left ^ right)  # symmetric difference

Set iteration order is not a contract for presentation. Sort values when deterministic output matters: for item in sorted(seen): ....

Create an empty set with set(). The literal {} creates an empty dictionary.

Set elements must be hashable. Strings, numbers, and tuples containing hashable values can be elements; a list cannot.

4. Dictionaries: key-value lookup

A dictionary maps unique keys to values. Retrieve a value by its key instead of a numeric sequence position.

prices = {"tea": 3, "coffee": 4}
print(prices["tea"])  # 3

prices["cocoa"] = 5
prices["tea"] = 4

if "coffee" in prices:
    print(prices["coffee"])

removed = prices.pop("cocoa")
print(removed)  # 5
print(list(prices.keys()))

summary = {name: price * 2 for name, price in prices.items()}
print(summary)

Safe lookup and iteration

Indexing a missing key raises KeyError. Use get when a default is appropriate.

stock = {"pens": 12}
print(stock.get("paper", 0))  # 0

for name, count in stock.items():
    print(name, count)

Dictionary keys must be hashable. A list cannot be a key because it can change; a tuple of hashable values can be used.

5. Queues with collections.deque

A FIFO queue returns the item that arrived first. A list can model a queue, but removing from the front shifts the remaining elements and is slow for queue behavior. The Python tutorial recommends collections.deque for fast appends and pops at both ends.

from collections import deque

queue = deque(["first", "second"])
queue.append("third")
print(queue.popleft())  # first
print(queue)            # deque(['second', 'third'])

queue.appendleft("urgent")
print(queue.pop())      # third

Use deque(maxlen=...) for a bounded rolling buffer. Calling popleft on an empty deque raises IndexError; check truthiness first or handle the exception.

6. How to choose the right structure

Requirement Choice Reason
Keep order and edit items list Mutable sequence with indexing and slicing
Group fixed-position values tuple Slots cannot be reassigned
Remove duplicates set Elements are unique
Test membership repeatedly set Expresses membership directly
Look up by identifier dict Maps a key to a value
Process arrivals FIFO deque Designed for both-end operations
Preserve input order while deduplicating dict.fromkeys(values) Dictionary keys are unique while retaining insertion order
values = ["a", "b", "a", "c"]
unique_in_input_order = list(dict.fromkeys(values))
print(unique_in_input_order)  # ['a', 'b', 'c']

7. Combining structures in real programs

Nested structures model records and collections of records.

orders = [
    {"id": 101, "items": ("book", "pen"), "paid": True},
    {"id": 102, "items": ("notebook",), "paid": False},
]

paid_ids = [order["id"] for order in orders if order["paid"]]
all_items = {item for order in orders for item in order["items"]}

print(paid_ids)  # [101]
print(all_items) # unique items, unordered

Choose each layer for its job: a list for ordered records, a dictionary for named fields, a tuple for fixed item groups, and a set for unique aggregation.

8. Troubleshooting common errors

Error or symptom Cause Fix
IndexError: list index out of range The index is outside the sequence Check len(items), valid indexes, or iterate directly
KeyError A dictionary key is absent Use key in mapping, get, or handle the exception
TypeError: unhashable type: 'list' A mutable list was used as a set element or dictionary key Use an immutable representation such as a tuple
Set output changes order Sets are unordered Use sorted(set_value) for display
Tuple assignment fails Tuple slots cannot be reassigned Create a new tuple, or use a list when fields must change
Queue processing becomes slow Removing from the front of a list shifts elements Use collections.deque and popleft
Changing a list while iterating skips items Indexes move as elements are removed Build a filtered list or iterate over a copy

9. Performance, reliability, and cost considerations

These structures are primarily a correctness and clarity choice. The official tutorial specifically warns that front removal from a list is inefficient for queues and recommends deque. Avoid claiming a universal fastest structure without measuring your own workload.

  • Use the structure that states your intent clearly.
  • Keep keys and values consistent so lookups are predictable.
  • Do not depend on set ordering for serialized output or user interfaces.
  • For large data, consider memory usage and whether streaming iteration is better than building a list.
  • When behavior matters, write small tests for empty collections, missing keys, duplicate inputs, and nested mutable values.

10. A runnable practice script

from collections import deque

def main():
    scores = [8, 10, 9]
    scores.append(7)

    point = (3, 5)
    x, y = point

    tags = {"python", "data", "python"}

    prices = {"tea": 3, "coffee": 4}
    prices["cocoa"] = 5

    queue = deque(["first", "second"])
    queue.append("third")

    print("scores:", scores)
    print("point:", x, y)
    print("tags:", sorted(tags))
    print("tea price:", prices["tea"])
    print("next job:", queue.popleft())

if __name__ == "__main__":
    main()

11. Or skip the browser setup

If your Python application needs screenshots of documentation, reports, or data pages, ScreenshotNeo provides a website screenshot API and MCP server. You can keep learning Python data structures without installing or managing a browser.

One GET request returns a PNG, JPEG, WebP, or PDF. See the ScreenshotNeo API documentation for all options.

cURL

curl -G "https://api.screenshotneo.com/v1/shot" \
  -d access_key=YOUR_API_KEY \
  --data-urlencode url=https://docs.python.org/3/tutorial/datastructures.html \
  -o shot.webp

Python

import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={
        "access_key": "YOUR_API_KEY",
        "url": "https://docs.python.org/3/tutorial/datastructures.html",
    },
    timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)

Node.js

const q = new URLSearchParams({
  access_key: 'YOUR_API_KEY',
  url: 'https://docs.python.org/3/tutorial/datastructures.html'
});
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`${res.status} ${res.statusText}`);
const fs = require('node:fs');
fs.writeFileSync('shot.webp', Buffer.from(await res.arrayBuffer()));

ScreenshotNeo accepts cookie and consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the result with X-Page-Verdict and X-Billed headers. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000.

Create your free ScreenshotNeo account.

12. FAQ

What are data structures in Python?

They are ways to organize values so your program can store, retrieve, update, and process data. Lists, tuples, sets, dictionaries, and deques cover many everyday cases.

Should I use a list or tuple?

Use a list when the sequence must change. Use a tuple when the group’s positions should remain fixed.

When is a set better than a list?

Use a set when uniqueness or membership is the main requirement and element order does not matter.

Can a dictionary key be a list?

No. Keys must be hashable; use an immutable alternative such as a tuple when its contents are hashable.

Is a deque a built-in literal?

No. Import it from collections; it is part of Python’s standard library.

For the canonical behavior and additional examples, read the Python Data Structures tutorial.