Skip to main content
Back to module
Python Fundamentals · Data Structures

Lists and tuples

Reading27mLesson 1 of 3 in this module

Store ordered data in lists, index and slice it, sort it, and use tuples for fixed groups of values.

Why it matters

Real data comes in collections: a week of temperatures, the students in a class, the rows of a file. A list holds many values in order under one name, so you can loop over them, pick out parts and sort them. A tuple is its fixed-size cousin, ideal for a group of values that belong together, such as a coordinate.

Creating and indexing lists

temps = [18, 21, 19, 25, 23, 17, 20]
names = ["Ada", "Grace", "Katherine"]
empty = []
mixed = ["sample-01", 23.4, True]   # allowed, but usually one type per list is clearer

Each item has a position, its index, starting at 0. Negative indexes count from the end:

print(temps[0])     # 18   first item
print(temps[3])     # 25
print(temps[-1])    # 20   last item
print(temps[-2])    # 17
print(len(temps))   # 7

Asking for a position that does not exist, such as temps[7], raises IndexError: list index out of range. The last valid index is always len(temps) - 1.

Slicing

A slice list[start:stop] gives a new list from start up to, but not including, stop, the same rule as range:

temps = [18, 21, 19, 25, 23, 17, 20]

print(temps[0:3])   # [18, 21, 19]   first three
print(temps[:3])    # [18, 21, 19]   start defaults to 0
print(temps[4:])    # [23, 17, 20]   stop defaults to the end
print(temps[-2:])   # [17, 20]       last two
print(temps[::2])   # [18, 19, 23, 20]  every second item (step 2)
print(temps[::-1])  # [20, 17, 23, 25, 19, 21, 18]  reversed

Slicing never raises an IndexError; out-of-range bounds are simply trimmed. Strings slice the same way: "Python"[:3] is "Pyt".

Changing a list

Lists are mutable: you can change them after they are created.

queue = ["Ada", "Grace"]
queue.append("Katherine")       # add to the end
queue.insert(0, "Alan")         # insert at position 0
queue[1] = "Ada L."             # replace an item
removed = queue.pop()           # remove and return the last item
queue.remove("Grace")           # remove the first matching value
print(queue)                    # ['Alan', 'Ada L.']
print("Alan" in queue)          # True

Other useful tools: max(temps), min(temps), sum(temps), temps.count(19) and temps.index(25) (position of the first 25).

Sorting: sorted() versus .sort()

temps = [18, 21, 19, 25]

ordered = sorted(temps)      # returns a NEW sorted list
print(ordered)               # [18, 19, 21, 25]
print(temps)                 # [18, 21, 19, 25]  unchanged

temps.sort(reverse=True)     # sorts IN PLACE, returns None
print(temps)                 # [25, 21, 19, 18]

A classic bug is temps = temps.sort(), which replaces your list with None. Use sorted() when you want to keep the original.

Copying and aliasing

Assigning a list to another name does not copy it. Both names point to the same list:

a = [1, 2, 3]
b = a
b.append(4)
print(a)        # [1, 2, 3, 4]  a changed too
c = a.copy()    # or a[:] or list(a): a real copy

Tuples

A tuple looks like a list with parentheses, but it cannot be changed:

location = (51.5072, -0.1276)    # latitude, longitude
print(location[0])               # 51.5072
location[0] = 0                  # TypeError: 'tuple' object does not support item assignment

Use a tuple when the number and meaning of the items is fixed: a coordinate, an RGB colour, a (name, score) pair. Unpacking assigns each item to its own name:

lat, lon = location
print(f"{lat:.2f}, {lon:.2f}")   # 51.51, -0.13

Functions that return several values (return low, high) are returning a tuple.

Lists of tuples: a small table

Lists and tuples combine into simple tables of records:

results = [("Ada", 91), ("Grace", 78), ("Katherine", 85)]

for name, score in results:
    print(f"{name:10} {score}")

best = max(results, key=lambda pair: pair[1])
print("Top:", best[0])   # Top: Ada

key= tells max (and sorted) what to compare: here, the score in position 1. lambda pair: pair[1] is a tiny unnamed function. You will see this pattern often.

Common mistakes

  • Off by one at the end. The last index is len(x) - 1, or simply x[-1].
  • x = x.sort(). .sort() returns None. Use x.sort() alone or x = sorted(x).
  • Accidental aliasing. b = a shares the list; use a.copy() for an independent copy.
  • Forgetting the comma in a one-item tuple. (5) is just the number 5; (5,) is a tuple.
  • Confusing append and extend. a.append([4, 5]) adds one item (a list); a.extend([4, 5]) adds two.

Quick recap

  • Lists are ordered and mutable; index from 0, or from the end with negatives.
  • Slices [start:stop:step] return new lists and exclude stop.
  • append, insert, pop, remove change a list in place.
  • sorted() returns a new list; .sort() changes the list and returns None.
  • Tuples are fixed groups of values; unpack them with a, b = pair.

Try it

In the Do tab you will slice a week of temperatures, sort a copy without changing the original, and unpack a coordinate tuple.

Also in this lesson: