Maintenance

Site is under maintenance — quizzes are still available.

Go to quizzes

Collect data with lists and tuples

Learn to collect and organize data in Python using lists and tuples. This lesson explains their differences, typical use cases, and how to choose between them in your code.

Focus: collect data with lists and tuples

Sponsored

When you start writing Python programs that go beyond a few variables, you quickly hit a wall: where do you store multiple related values? Cramming them into separate variables (score_1, score_2, …) is brittle, unreadable, and impossible to loop over. That’s the pain this lesson solves. You’ll learn how to collect data with lists and tuples — two of Python’s most fundamental built-in collection types — enabling you to group, access, and iterate over data effortlessly.

The problem this lesson solves

Imagine you’re tracking the top three scores of a game. Without collections, you’d write:

high_score_1 = 9800
high_score_2 = 7500
high_score_3 = 6200

Now add a fourth score. You’d have to invent high_score_4, remember to update every place you used the old variables, and you can’t use a loop to process them. This approach breaks down the moment you have 10, 100, or an unpredictable number of items.

Lists and tuples solve this by letting you group related data into a single container. You can access items by position, iterate over them, and (for lists) modify the group as your program runs. Without these tools, you’d either repeat yourself endlessly or resort to fragile hacks like manually allocating array indices in other languages.

Core concept / mental model

Think of a list as a mutable shopping basket — you can add items, remove them, or change them while you shop. A tuple, on the other hand, is like a sealed photo album: once you place a picture, its order and contents are fixed.

Both are ordered sequences, meaning the first item stays first, the second stays second, and so on. But lists can change length and contents; tuples cannot.

Key definitions

  • List: Created with square brackets [1, 2, 3]. Supports append(), remove(), item assignment (my_list[0] = 10).
  • Tuple: Created with parentheses (1, 2, 3). Immutable — no method changes the tuple in-place. Used for fixed data (e.g., days of the week, coordinates).

Pro tip: Use tuples by default. If you later find you need mutability, switch to a list. This reduces unintended changes in your code.

How it works step by step

1. Creating collections

# List
scores = [95, 82, 77]     # mutable

# Tuple
coordinates = (40.7128, -74.0060)   # immutable

Python deduces the type: type(scores) returns <class 'list'>, type(coordinates) returns <class 'tuple'>.

2. Accessing items

Both use zero-based indexing — the first item is at index 0.

scores[0]    # 95
coordinates[1]  # -74.0060

Negative indices count from the end: - scores[-1]77 (last item) - scores[-2]82

3. Slicing

Get a subset with [start:stop:step]:

top_scores = [9800, 7500, 6200, 5100, 4300]
print(top_scores[:3])   # [9800, 7500, 6200] — items 0,1,2
print(top_scores[1:4])  # [7500, 6200, 5100] — items 1,2,3

4. Iteration

for score in scores:
    print(score * 2)   # 190, 164, 154

This works identically for tuples.

5. Modifying lists (but not tuples)

scores.append(68)      # [95, 82, 77, 68]
scores[1] = 88         # [95, 88, 77, 68]
scores.remove(77)      # [95, 88, 68]

# Trying the same on a tuple raises TypeError
# coordinates[0] = 41.0   # Error!

Hands-on walkthrough

Let’s build a small program that collects temperature readings and calculates the average.

# Step 1: Collect data in a list
temperatures = []  # start empty

# Simulate adding readings
readings = [22.5, 23.1, 21.8, 24.0, 22.9]
for temp in readings:
    temperatures.append(temp)

print("All temperatures:", temperatures)

Output:

All temperatures: [22.5, 23.1, 21.8, 24.0, 22.9]

Now let’s compute the average and find the max:

average = sum(temperatures) / len(temperatures)
print(f"Average: {average:.2f}")

highest = max(temperatures)
lowest = min(temperatures)
print(f"Highest: {highest}, Lowest: {lowest}")

Output:

Average: 22.86
Highest: 24.0, Lowest: 21.8

Finally, sort the list in descending order:

temperatures.sort(reverse=True)
print("Sorted descending:", temperatures)

Output:

Sorted descending: [24.0, 23.1, 22.9, 22.5, 21.8]

Pro tip: len(), sum(), max(), min() work on both lists and tuples. Sorting tuple returns a new list — it doesn’t mutate the original.

Let’s do a tuple example — storing a fixed sensor location:

def get_sensor_location():
    # returns immutable (latitude, longitude)
    return (51.5074, -0.1278)

sensor = get_sensor_location()
print(f"Latitude: {sensor[0]}, Longitude: {sensor[1]}")

Output:

Latitude: 51.5074, Longitude: -0.1278

Notice sensor[0] = 52.0 would crash — that’s the safety of immutability.

Compare options / when to choose what

Scenario Use list Use tuple
Scores that change as players improve
A point in 2D space (forever fixed)
Return multiple values from a function ❌ (prefer tuple)
You need to delete or insert items
Data that should not be accidentally changed

Rule of thumb: Start with a tuple. Convert to a list only when your code demands mutation. This habit prevents subtle bugs where data changes unintentionally.

Troubleshooting & edge cases

IndexError: list index out of range

items = [10, 20]
print(items[5])  # Error!

Check length with len(items) before accessing indices. Or use safe slicing: items[5:6] returns [] instead of crashing.

Modifying a tuple

# Causes: TypeError: 'tuple' object does not support item assignment
fixed = (1, 2)
fixed[0] = 10   # Error

Fix: Assign the entire tuple: fixed = (10, 2). Or convert to list, modify, convert back.

Forgetting that list methods return None

sorted_list = scores.sort()  # ❌ sort() returns None
print(sorted_list)           # None

Fix: Use new_list = sorted(scores) or scores.sort() then use scores.

Mutable lists as default arguments (common pitfall)

def add_item(item, collection=[]):
    collection.append(item)
    return collection

print(add_item(1))  # [1]
print(add_item(2))  # [1, 2]  — probably not what you expected!

Fix: Use collection=None and initialize inside the function.

What you learned & what's next

You now know how to collect data with lists and tuples: - Lists are mutable ordered collections; tuples are immutable. - Both support indexing, slicing, and iteration. - Use lists when data changes, tuples when it shouldn’t. - Common pitfalls include index errors, accidentally modifying tuples, and mutable default arguments.

Next up: You’ll master dictionaries — Python’s key-value data structure, perfect for storing and looking up data by name rather than position. You’ll connect lists and tuples to build richer data structures like a to-do app or a config manager.

Practice recap

Open a Python REPL and create a list of three cities you’ve visited. Append a fourth city, then print the second and last city. Next, define a tuple with your birth year, month, and day. Try to change the day — see the error. Finally, use a list to collect five random numbers, sort descending, and print the top three using slicing. This solidifies the mutable vs. immutable boundary.

Common mistakes

  • Forgetting that list.sort() returns None — always use it in-place or call sorted() for a new list.
  • Trying to modify a tuple item, getting a TypeError: 'tuple' object does not support item assignment.
  • Using a mutable list as a default function argument, which accumulates changes across calls.
  • IndexError when accessing positions beyond the length — always check len() first or use slicing safely.

Variations

  1. Use array.array from the standard library for homogeneous numerical data with less memory overhead.
  2. Use collections.deque for fast appends and pops from both ends, at the cost of slower indexing.
  3. In Python 3.9+, use list | tuple type hints for function parameters that accept either.

Real-world use cases

  • Storing a daily log of user registration timestamps in a list, then calculating average time or finding the latest entry.
  • Returning (status_code, response_body) from a function as a tuple, ensuring the caller doesn’t accidentally modify the status code.
  • Keeping a fixed configuration of (host, port, timeout) as a tuple so the setup is read-only across the application.

Key takeaways

  • Lists ([...]) are mutable; tuples ((...)) are immutable — choose based on whether data changes.
  • Both support zero-based indexing, negative indices, slicing, and iteration.
  • Use len(), sum(), max(), min() on both; sort() works only on lists (and returns None).
  • Avoid mutable default arguments (e.g., def f(x=[])) — use None and initialize inside.
  • Prefer tuples for fixed data (coordinates, function return values) to prevent accidental changes.
  • Always check length or use safe slicing to avoid IndexError when accessing items.

Sponsored

Sponsored

Discussion

Questions, corrections, and tips help everyone reading this page.

0 comments

Add a comment

Shown publicly with your comment.

Be constructive · max 4,000 characters

No comments yet — start the thread.

Related tutorials, quizzes, and articles for this topic.