Python Atlas
Foundations

Lists and Tuples

Model ordered data with mutable lists and fixed-shape immutable tuples.

Lists and tuples are ordered sequences. Both support iteration, indexing, slicing, membership, and len. Their main difference is mutability.

Lists: editable ordered collections

tasks = ["read", "practice", "review"]
print(tasks[0])      # read
print(tasks[-1])     # review
print(tasks[1:])     # ['practice', 'review']
print("read" in tasks)  # True

Lists may contain mixed types, but collections of one conceptual kind are usually easier to process.

Common methods mutate the list:

tasks.append("build")
tasks.extend(["test", "share"])
tasks.insert(1, "plan")
tasks.remove("review")  # removes first equal value
last = tasks.pop()      # removes and returns final value

remove raises ValueError if the value is absent; pop raises IndexError when the selected position does not exist.

Other useful methods:

numbers = [3, 1, 3, 2]
print(numbers.count(3))  # 2
print(numbers.index(2))  # 3

numbers.reverse()
numbers.clear()

Sorting lists

list.sort() mutates a list and returns None. sorted() accepts any iterable and returns a new list:

scores = [72, 95, 81]
ascending = sorted(scores)
print(scores)     # [72, 95, 81]
print(ascending)  # [72, 81, 95]

scores.sort(reverse=True)
print(scores)     # [95, 81, 72]

Use a key function to define what is compared:

names = ["Grace", "ada", "Guido"]
print(sorted(names, key=str.casefold))

Sorting is stable: records with equal keys preserve their original relative order.

Copying and nested lists

Assignment shares one list:

original = ["a", "b"]
alias = original
alias.append("c")
print(original)  # ['a', 'b', 'c']

A shallow copy creates a new outer list:

copy = original.copy()
copy.append("d")

Nested objects remain shared in a shallow copy. Use copy.deepcopy only when truly independent nested mutable data is required; often a clearer data model avoids the need.

Do not create a grid with repeated inner-list references:

# wrong: rows = [[0] * 3] * 3
rows = [[0] * 3 for _ in range(3)]
rows[0][0] = 1
print(rows)  # [[1, 0, 0], [0, 0, 0], [0, 0, 0]]

Tuples: fixed-shape records

Tuples cannot have elements added, removed, or replaced:

point = (4, 7)
x, y = point
print(x, y)  # 4 7

Parentheses do not create a one-item tuple; the comma does:

singleton = (42,)
not_a_tuple = (42)

Tuples can contain mutable objects, and those nested objects can still change:

record = ("Ada", ["math", "poetry"])
record[1].append("computing")

The tuple's references are fixed; the referenced list is not immutable.

Choosing list versus tuple

Choose a list when:

  • items form a changing collection;
  • you will append, remove, reorder, or replace items;
  • all elements play the same conceptual role, such as a list of scores.

Choose a tuple when:

  • positions form a fixed record, such as (latitude, longitude);
  • the structure should communicate “do not resize or reassign”;
  • hashable contents are needed as a dictionary key or set member;
  • a function naturally returns several related values.

Neither is automatically “better” or meaningfully faster for ordinary design decisions. Choose the type that communicates the data's intended behavior.

Sequence unpacking

first, second, third = ["red", "green", "blue"]
head, *middle, tail = [10, 20, 30, 40, 50]

print(head)    # 10
print(middle)  # [20, 30, 40]
print(tail)    # 50

Exactly one starred target may collect remaining items. Unpacking works with any iterable, not only lists and tuples.

Common mistakes

  • Assigning the result of a mutating method: items = items.append(value) makes items None.
  • Modifying a list while iterating over it, which can skip elements.
  • Expecting slicing or .copy() to deeply copy nested values.
  • Omitting the comma in a one-item tuple.
  • Using a tuple for data that must be updated frequently.
  • Relying on numerical positions for a large record; a class or named record is clearer.

Decision guidance

  • Need order, duplicates, and mutation? Use a list.
  • Need order and a small fixed structure? Use a tuple.
  • Need fast lookup by meaningful keys? Use a dictionary.
  • Need unique membership with no positional meaning? Use a set.
  • Use sorted(data) when the original order matters; use data.sort() when deliberate mutation is appropriate.

Practice

  1. Add and remove tasks from a list without assigning method return values.
  2. Sort names case-insensitively while preserving the original list.
  3. Represent an RGB color as a tuple and unpack its channels.
  4. Build a 4-by-4 independent grid and change only its bottom-right cell.

LEARNING RECORD

Finish this lesson

Mark it complete when you can explain the main decision without looking.

KNOWLEDGE CHECK

Lists and Tuples

1Which statement about sorting is correct?
2Why is `[[0] * 3 for _ in range(3)]` preferred for a mutable 3-by-3 grid?