A list holds many values in order, and you can change it after you make it. It is the collection you will use most.
scores = [88, 72, 95, 61]
mixed = ["Ada", 36, True, 3.5] # types can be mixed, though rarely should be
empty = []
print(scores)
print(scores[0], scores[-1]) # first and last
print(scores[1:3]) # a slice - same rules as strings
print(len(scores))
print(95 in scores)Indexing and slicing work exactly as they did for strings on Day 1 — zero-based, negatives count from the end, slices exclude the stop.
Lists can be changed
This is the big difference from strings. A list is mutable: you can replace, add and remove items in place.
tasks = ["write", "test"]
tasks.append("ship") # add one to the end
tasks.insert(0, "plan") # add at a position
tasks.extend(["deploy", "rest"]) # add several
print(tasks)
tasks[1] = "WRITE" # replace by index
removed = tasks.pop() # remove and return the last
tasks.remove("test") # remove the first match by value
print(tasks, "| removed:", removed)append versus extend
append adds its argument as a single item — append([1, 2]) gives you a list
inside your list. extend adds each item of what you give it. When the result
surprises you, this is usually why.
Sorting
sort() reorders the list itself and returns nothing. sorted() leaves the
original alone and hands back a new list. Choosing the wrong one is a classic
bug.
scores = [88, 72, 95, 61]
print(sorted(scores)) # a new sorted list
print(scores) # original untouched
scores.sort()
print(scores) # now the original is sorted
scores.sort(reverse=True)
print(scores)
# key= decides what to sort by.
words = ["banana", "fig", "cherry"]
print(sorted(words, key=len))scores = scores.sort() destroys your data
sort() returns None, so assigning its result replaces your list with
nothing. If you want a sorted copy, use sorted().
Looping over lists
prices = [4.99, 12.50, 3.25, 8.00]
for price in prices:
print(f"${price:.2f}")
print("Total:", sum(prices))
# Building a new list from an old one.
with_tax = []
for price in prices:
with_tax.append(round(price * 1.2, 2))
print(with_tax)That last pattern — start empty, loop, append — is so common that Python has a one-line form for it. You will meet comprehensions on Day 4.
Copying, and the trap
Assigning a list does not copy it. Both names end up pointing at the same list, and a change through one is visible through the other.
original = [1, 2, 3]
alias = original # NOT a copy
alias.append(4)
print("original:", original)
print("alias: ", alias)
print("same object?", original is alias)
copy = original[:] # a real copy (or list(original), or original.copy())
copy.append(5)
print("original:", original)
print("copy: ", copy)This is not a wart — it is the same rule every language with references has, and it is what makes passing large lists to functions cheap. You simply have to know it is happening.
Nested lists
A list can hold lists, which is how you get grids and tables.
grid = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
]
print(grid[1]) # the middle row
print(grid[1][2]) # row 1, column 2
for row in grid:
for value in row:
print(f"{value:3}", end="")
print()Score report
From the list of scores, print the count, the highest, the lowest, the average to one decimal place, and the three highest scores in descending order.
scores = [88, 72, 95, 61, 79, 93, 84]
# Your code hereShow one solution
scores = [88, 72, 95, 61, 79, 93, 84]
print(f"Count: {len(scores)}")
print(f"Highest: {max(scores)}")
print(f"Lowest: {min(scores)}")
print(f"Average: {sum(scores) / len(scores):.1f}")
print(f"Top 3: {sorted(scores, reverse=True)[:3]}")sorted(...)[:3] — sort a copy descending, then slice the first three. Using
sorted rather than sort leaves the original list in its original order,
which the rest of a program may depend on.
What you learned
- Lists are ordered, indexable, sliceable and mutable.
append,insert,extend,popandremovechange a list in place.sort()reorders in place and returnsNone;sorted()returns a new list.key=controls what sorting compares.- Assignment shares a list;
[:],list()or.copy()make a real copy.