JEPA4Japan · tutorials

Lists, Tuples, and Sequence Thinking

1,031 words 5 min read #Python

Store ordered data and understand identity, aliasing, mutability, copying, unpacking, and sequence operations.

Course progress Course outline 24 of 24 lessons available

Lists are trays; tuples are sealed cards

Sometimes one value is not enough. You may need several study topics, seven daily scores, or one (day, minutes) record. Python gives ordered groups two useful shapes.

  1. List items may move in and out
  2. Tuple positions make one fixed record
  3. Sequence read items in order
Use a list for a changing collection and a tuple for a fixed-shaped record.

Both are sequences. Their items stay in order, start at position 0, and work with len(), in, indexes, and slices.

topics = ["Strings", "Lists", "Dictionaries"]

print(len(topics))
print(topics[0])
print(topics[-1])
print(topics[1:3])
print("Lists" in topics)
3
Strings
Dictionaries
['Lists', 'Dictionaries']
True

A slice stops before its end and makes a new outer sequence. A single missing index raises IndexError; a slice may safely reach beyond the end.

A list can grow and shrink

Lists use square brackets and are mutable: their contents can change.

queue = ["Strings", "Lists"]
queue.append("Tuples")
queue.extend(["Dictionaries", "Sets"])
queue.insert(1, "Review")

print(queue)
['Strings', 'Review', 'Lists', 'Tuples', 'Dictionaries', 'Sets']

append(x) adds one item. extend(things) adds every item from things. Appending ["A", "B"] creates one nested list; extending it adds two strings.

To remove by value, use remove(). To remove by position and keep the removed value, use pop():

queue = ["Strings", "Review", "Lists"]
queue.remove("Review")
finished = queue.pop(0)

print(finished)
print(queue)
Strings
['Lists']

Boundary reminder: remove("missing") raises ValueError, and pop() on an empty list raises IndexError. When absence is normal, check with in or check that the list is non-empty first.

Two name tags can point to one tray

Assignment does not copy a list. It puts another name tag on the same tray.

  1. One list ["Strings", "Lists"]
  2. plan first name tag
  3. alias second name tag
  4. Change once both names see it
alias = plan shares one mutable object.
plan = ["Strings", "Lists"]
alias = plan
snapshot = plan.copy()

alias.append("Tuples")

print(plan)
print(snapshot)
print(alias is plan)
print(snapshot is plan)
['Strings', 'Lists', 'Tuples']
['Strings', 'Lists']
True
False

is asks “the exact same object?”; == asks “equal contents?” copy() or plan[:] makes a new outer list. This is a shallow copy, so nested mutable items remain shared:

week = [["Mon", 20], ["Tue", 30]]
snapshot = week.copy()

week.append(["Wed", 40])
week[0][1] = 99

print(snapshot)
print(week)
[['Mon', 99], ['Tue', 30]]
[['Mon', 99], ['Tue', 30], ['Wed', 40]]

The new Wednesday tray exists only in week, but both outer lists still point to the same inner Monday tray.

A tuple keeps one record’s shape

Tuples usually use parentheses. They are immutable sequences: no append(), no remove(), and no item assignment.

  1. Monday position 0
  2. 45 minutes position 1
  3. Fixed pair the record stays two parts
A tuple is useful when every position has a lasting job.
record = ("Monday", 45)
day, minutes = record

print(day)
print(minutes)
Monday
45

Unpacking needs exactly as many names as items unless you use a starred target. A one-item tuple needs a comma: ("Lists",) is a tuple, but ("Lists") is just a string. A tuple itself cannot change, though a mutable list placed inside one can still change; tuples are not deep freezers.

Tiny project: Three-Day Study Log

Create study_log.py. This complete program uses only built-in Python tools. Day records are fixed tuples; the log and topic queue are lists. A snapshot proves the queue was copied, not aliased.

study_log = [
    ("Monday", 20),
    ("Tuesday", 35),
    ("Wednesday", 35),
]
topic_queue = ["Strings", "Lists", "Dictionaries"]

original_plan = topic_queue.copy()

finished = topic_queue.pop(0)
topic_queue.append("Sets")

total = 0
for day, minutes in study_log:
    total += minutes
    print(f"{day}: {minutes} minutes")

average = total / len(study_log)

print(f"Total: {total} minutes")
print(f"Average: {average:.1f} minutes")
print(f"Finished: {finished}")
print(f"Original: {original_plan}")
print(f"Now: {topic_queue}")
print(f"Snapshot safe: {original_plan == ['Strings', 'Lists', 'Dictionaries']}")

Run python3 study_log.py and check the ending:

Monday: 20 minutes
Tuesday: 35 minutes
Wednesday: 35 minutes
Total: 90 minutes
Average: 30.0 minutes
Finished: Strings
Original: ['Strings', 'Lists', 'Dictionaries']
Now: ['Lists', 'Dictionaries', 'Sets']
Snapshot safe: True

The program always has three records, so division is safe. If an empty log were allowed, you would need to decide what “average” means before dividing.

Three tiny missions

  1. Append or extend? Try both with ["Tuples", "Sets"]. Predict which result will be nested.
  2. Copy detective. Copy [["Mon", 10]], then change the inner 10. Explain why both outer lists see the change.
  3. Tuple inspector. Make (topic, minutes, done), unpack it into three names, and print one sentence.

You are ready for Chapter 7 when…

  • you can read sequence items with indexes and slices;
  • you can choose append(), extend(), remove(), or pop();
  • you can explain why an alias shares list changes;
  • you can make a shallow copy and describe its nested-list boundary;
  • you can choose a changing list or a fixed-shaped tuple;
  • you can create a one-item tuple and unpack records correctly;
  • you can run the Study Log and see Snapshot safe: True.

Next, you will replace numbered positions with meaningful dictionary keys and use sets when “only one of each” matters.