← Back to the Introduction to Computer Science outline The Course Maker
← Introduction to Computer Science outline
Week 9 · Chapter

Chapter 9 — Lists

Introduction to Computer Science Free sample edition

The module's primary reading · ~40–50 minutes · Objective 6 (choose and use Python's built-in collections (lists, tuples, dictionaries, and sets) with indexing, slicing, mutation, methods, and iteration, and explain aliasing versus copying) and Objective 4 (write while loops and for loops over range(), using counters, accumulators, nested loops, and break, and recognize and repair an infinite loop and an off-by-one error) · Read it first this week; the lecture, the slides, the tutorial, the quiz, and the Coding Lab all build on it.


In plain language

So far every value in your programs has lived in its own variable, one name per number or string. This week you meet a list (one name that holds a whole row of values, in order), so seven days of reading fit under a single name. You will read any item (one value in the list) by its position, cut out pieces, and change the list after you make it, which a string never allowed. You will also learn the one surprise that trips up almost everyone: giving a list a second name does not make a second list. As always, you predict what each program prints and then run it to check.

Why you already care about this

Your phone keeps a grocery list of 6 items. You add milk at the end, slip eggs in at the top, and cross off bread, so 6 items become 7, and the list you see is the same list you changed. Nobody makes a new variable for every grocery item. A music app does the same with a playlist of 20 songs: one name, many songs, in an order you can rearrange.

Programs need that too. Last week's review closed the first half of the course with single values: one pages_read, one goal, one total. This week the reading log keeps a whole week of daily pages, 7 numbers under one name, and it walks that list to find the total, the average, and the biggest day. Along the way you will change lists with methods such as append and pop, and you will find out why the same change can show up under two names at once.

By the end of this chapter you will be able to:

  • make a list, read any item by its index from the front or the back, and take a slice;
  • explain why a slice is a new list and why an index past the end raises IndexError;
  • walk a list with a for loop to compute a total, an average, and a maximum by hand;
  • change a list in place with index assignment, append, insert, pop, and remove, and predict what each method hands back;
  • tell sorted() from .sort() and append from extend;
  • predict what a second name sees after a change, telling an alias from a copy and is from ==;
  • avoid changing a list while a loop walks it, and check a chatbot's claim with a run.

Carry this line with you: two names can share one list — a copy makes two.

Where we are

  • Already covered: Weeks 1 to 3 gave you printing, variables, strings, indexing from 0, and half-open slices. Week 4 gave you conditions. Weeks 5 and 6 gave you loops, counters, and accumulators. Week 7 gave you functions and None, and Week 8 reviewed it all.
  • This week: lists, indexing and slicing them, walking them for a total, an average, and a maximum, changing them with methods, aliasing against copying, and the mutate-while-iterating trap.
  • How they connect: a list is indexed and sliced exactly like a string, walked exactly like a string in a for loop, and its methods return values or None exactly as Week 7's functions did.
  • Where we're going next: Week 10, Tuples, Dictionaries & Sets, adds three more containers and teaches you how to choose the right one.

Three earlier ideas carry most of the weight. From Week 3, positions start at 0 and a slice keeps its start and drops its stop, so "PYTHON"[1:4] printed YTH. From Week 6, a for loop hands you each item of a sequence, and an accumulator starts before the loop. From Week 7, a function that only does work and has no return hands back None. Spend extra time on Sections 5 and 6; next week's dictionaries lean on both.

1. Making a list: many values under one name

A bus has numbered seats. You do not give each seat its own street address; you say "seat 3 on this bus." A list works the same way. The bus is one name, and each seat is a numbered position inside it.

A list is an ordered collection of values kept under one name, written in square brackets with commas between the values, which a program can read by position and change after it is made.

An item is one of the values stored in a list; each item sits at a numbered position, starting from 0 at the front.

Worked example — a week of the reading log. The reading log now keeps the pages read on each of 7 days. Predict all four lines before you read the output.

daily = [12, 40, 25, 0, 33, 17, 27]
print(daily[0])
print(daily[-1])
print(daily[1:3])
print(len(daily))

Output

12
27
[40, 25]
7

Here is the reasoning, line by line.

  1. daily[0] is the item at index 0, the first day: 12.
  2. daily[-1] counts back from the end, as negative indexes did in a string: the last day, 27.
  3. daily[1:3] takes indexes 1 and 2 and stops before 3, so it prints the list [40, 25].
  4. len(daily) counts the items: 7 days.

In words: one name now holds the whole week, and every rule you learned for strings in Week 3 reads it the same way.

An empty list is a list with no items in it, written as a pair of square brackets with nothing between them, often used as the starting point for a list a loop will fill.

cart = []
print(cart)
print(len(cart))

Output

[]
0

Here is a second setting, an illustrative bike-share station that lists how many bikes sit at each of 5 docks.

bikes = [8, 3, 11, 6, 5]
print(bikes[2])
print(bikes[-2])
print(len(bikes))

Output

11
6
5

Index 2 is the third dock, 11 bikes. Index −2 is the second dock from the end, 6 bikes. There are 5 docks, so the last index is 5 − 1 = 4.

Worked example — one step too far. The pinned error program asks for index 3 of a list with 3 items. Predict what happens.

daily = [12, 40, 25]
print(daily[3])

Output

IndexError

Nothing printed. The last index of a 3-item list is 3 − 1 = 2, so index 3 is past the end, and the last line of the error names IndexError. This is a runtime error: the program started, and this line stopped it.

Misconception check. Students often think the last item of a 7-item list is daily[7], because the list holds 7 things. That is tempting, because everyday counting ends on the count. But counting starts at 0, so the last index is always one less than the length, and daily[7] raises IndexError. The cure: reach the last item with daily[-1], or with an index of len(daily) - 1.

In practice (your tools). Open your free browser Python runner, type the four-line daily program, and press Run. Then add print(daily[7]) as a last line, predict the error type, and read the last line of the traceback to confirm it. The Python Tutorial's section 3.1.3, Lists, on docs.python.org, shows lists indexed and sliced exactly like strings.

Memory hook: count from 0 at the front; count back from the end.

2. Slicing: every slice is a brand-new list

A photocopy of the first page of a recipe is yours to scribble on. Your notes land on the copy, and the cookbook stays clean. A slice of a list works like that photocopy.

A slice of a list follows the same half-open rule you met in Week 3: it starts at its start index and stops before its stop index. What is new is that the result is a separate list. Change the slice, and the original does not move.

Worked example — change the slice, not the week. Predict both lines.

daily = [12, 40, 25, 0, 33, 17, 27]
first_three = daily[:3]
first_three[0] = 50
print(first_three)
print(daily[0])

Output

[50, 40, 25]
12

Here is the trace.

  1. daily[:3] has no start, so it begins at 0, and it stops before 3: the items 12, 40, and 25.
  2. Those three items go into a new list named first_three.
  3. first_three[0] = 50 changes the new list's first item.
  4. daily[0] is still 12, because daily was never touched.

Worked example — four slices of one list. The pinned to-do program ends with four slices of a list of tens.

nums = [10, 20, 30, 40, 50]
print(nums[1:3], nums[:2], nums[2:], nums[-1])

Output

[20, 30] [10, 20] [30, 40, 50] 50

nums[1:3] takes indexes 1 and 2. nums[:2] takes the first two. nums[2:] runs from index 2 to the end. nums[-1] is not a slice at all; it is one item, so it prints a bare 50 with no brackets. In words: a slice always prints as a list, and an index always prints as one item.

Misconception check. Students often think nums[1:3] includes index 3, so they expect three items. That is tempting, because 3 is written right there in the brackets. But the stop is never included, so nums[1:3] holds 3 − 1 = 2 items, [20, 30]. The cure: count stop minus start, and expect exactly that many items.

In practice (your tools). Paste the first_three program into Python Tutor at pythontutor.com and click Next one step at a time. Watch two separate list boxes appear, one for daily and one for first_three, and watch the 50 land only in the second box.

Memory hook: a slice is a photocopy, not the page.

3. Walking a list: a total, an average, and the biggest

A cashier adds up a receipt one line at a time, keeping a running total. A judge at a pie contest tastes each pie and remembers the best one so far, swapping it out only when a better pie comes along. Those are the two patterns this section runs over a list.

You already have both tools. Week 6's for loop hands you each item, and Week 5's accumulator starts at 0 and grows on every pass.

Worked example — the reading log's week. This is the reading log's Week 9 stage. Predict all four lines.

daily = [12, 40, 25, 0, 33, 17, 27]
total = 0
for pages in daily:
    total = total + pages
print(total)
print(total / len(daily))
biggest = daily[0]
for pages in daily:
    if pages > biggest:
        biggest = pages
print(biggest)
print(len(daily))

Output

154
22.0
40
7

Here is the reasoning.

  1. The first loop adds every day: 12 + 40 + 25 + 0 + 33 + 17 + 27 = 154.
  2. The average divides the total by the number of days: 154 ÷ 7 = 22.0. It prints 22.0, a float, because / always gives a float.
  3. The second loop starts biggest at the first day, 12. When it meets 40, it swaps 12 out; no later day beats 40, so it prints 40.
  4. len(daily) is 7.

In words: you read 154 pages this week, 22.0 a day on average, and 40 on your best day.

Here is the same pattern in a second setting, an illustrative receipt with four prices in dollars.

prices = [4, 6, 2, 8]
total = 0
for price in prices:
    total = total + price
print(total)
print(total / len(prices))

Output

20
5.0

The prices add to 4 + 6 + 2 + 8 = 20, and 20 ÷ 4 = 5.0 dollars per item on average.

Misconception check. Students often start the biggest-so-far at 0, because 0 feels like a safe "nothing yet." That is tempting, and it even works for the reading log. But try an illustrative week of winter low temperatures, all below zero:

temps = [-3, -8, -1]
biggest = 0
for t in temps:
    if t > biggest:
        biggest = t
print(biggest)

Output

0

No day reached 0, yet 0 printed, because no temperature ever beat the starting value. The cure: start the biggest-so-far at the list's own first item, temps[0]. With that one change the same program prints -1, the warmest day.

In practice (your tools). Paste the reading-log program into Python Tutor at pythontutor.com and step through the second loop. Watch biggest change once, from 12 to 40, and stay put for the other five days.

Memory hook: a total starts at 0; a biggest starts at the first item.

4. Changing a list: edits happen in place

A whiteboard by the door holds the household chores. You can rub out one chore and write another in its spot, add a chore at the bottom, or wedge one in at the top. Through all of that it is still the same whiteboard. A list is a whiteboard; a string, as you will see, is a printed card.

Changing a list in place describes a change made to the existing list itself, so every name that points at that list sees the change, instead of a new list being built.

Index assignment is a statement that puts a new value at one position of a list, written as the list name, the position in square brackets, an equals sign, and the new value.

Worked example — fix one reading. An illustrative weather log has a typo in its second temperature.

temps = [18, 21, 19]
temps[1] = 23
print(temps)

Output

[18, 23, 19]

Index 1 now holds 23. The list kept its length and its other items. A string refuses this. Try the same move on one:

word = "cat"
word[0] = "b"

Output

TypeError

The string cannot be changed, so Python raised TypeError. The same letters in a list change without complaint:

letters = ["c", "a", "t"]
letters[0] = "b"
print(letters)

Output

['b', 'a', 't']

A method is a function that belongs to a value and is called with a dot after that value, such as append after a list name, so it can read or change that particular value.

Four methods change a list in place:

  • append is the list method that adds one item to the end of a list in place and hands back None, even when the item it adds is itself a list.
  • insert is the list method that takes a position and an item, places the item at that position, shifts the later items one place to the right, and hands back None.
  • pop is the list method that removes an item, the last one or the one at the position given, and hands that removed item back to the code that called it.
  • remove is the list method that deletes the first item equal to the value it is given, searching by value rather than by position, and hands back None.

Worked example — the to-do list. This is the pinned list-methods program, minus its last line, which Section 2 already showed. Predict each line.

tasks = ["email", "lunch"]
tasks.append("gym")
print(tasks)
tasks.insert(0, "coffee")
print(tasks)
done = tasks.pop(0)
print(done, tasks)
tasks.remove("gym")
print(tasks)
print("lunch" in tasks, "gym" in tasks)

Output

['email', 'lunch', 'gym']
['coffee', 'email', 'lunch', 'gym']
coffee ['email', 'lunch', 'gym']
['email', 'lunch']
True False

Line by line:

  1. append("gym") adds gym at the end: three items.
  2. insert(0, "coffee") puts coffee at index 0 and shifts the rest right: four items.
  3. pop(0) takes the item at index 0 out of the list and hands it back, so done holds coffee and the list is back to three items.
  4. remove("gym") deletes the value gym: two items left.
  5. The in test asks whether a value is one of the items. Lunch is there, so True; gym is gone, so False.

In words: one list changed four times, and every change happened to that same list.

Misconception check. Students often think insert(0, "coffee") writes over the item at index 0, the way index assignment does. That is tempting, because both put a value at a position. But insert makes room: the list grows by one, and email moves to index 1. The cure: use insert to add and index assignment to replace, and check with len() after the change.

In practice (your tools). Type the to-do program into your browser runner and run it. Then add print(len(tasks)) after each method call and predict each length before you run it again. The Python Tutorial's section 5.1, More on Lists, on docs.python.org, lists every one of these methods.

Memory hook: insert makes room; index assignment replaces.

5. Return values: what each method hands back

When you return a library book, the desk gives you a receipt. When you drop a letter in a mailbox, you get nothing back. Both actions did something; only one handed you a thing to keep. List methods are split the same way, and Week 7 already gave you the name for "nothing back": None.

pop hands back the item it removed. append, insert, remove, and sort change the list and hand back None.

Worked example — print what comes back. Predict all three lines.

tasks = ["email", "lunch"]
print(tasks.append("gym"))
print(tasks.pop())
print(tasks)

Output

None
gym
['email', 'lunch']

The append worked, since the next line popped gym back off, but the value append handed back was None. pop() with no index took the last item and handed back gym.

sort is the list method that rearranges a list into order in place and hands back None, so assigning what it hands back to a name stores None.

Worked example — the sort that lost the list. The pinned program below looks reasonable. Predict it.

nums = [3, 1, 2]
nums = nums.sort()
print(nums)

Output

None

nums.sort() sorted the list, then handed back None, and the assignment put that None into nums. The sorted list is gone.

sorted() is the built-in function that builds and hands back a new list holding the items in order, leaving the original list exactly as it was.

Worked example — sorted() against .sort(). The pinned program shows both, side by side.

nums = [3, 1, 2]
print(sorted(nums))
print(nums)
result = nums.sort()
print(result)
print(nums)

Output

[1, 2, 3]
[3, 1, 2]
None
[1, 2, 3]

sorted(nums) handed back a new sorted list and left nums alone. nums.sort() changed nums itself and handed back None.

extend is the list method that adds every item of another list, one by one, to the end of a list in place and hands back None.

Worked example — append against extend. Predict the lengths on the last line.

a = [1, 2]
a.append([3, 4])
print(a)
b = [1, 2]
b.extend([3, 4])
print(b)
print(len(a), len(b))

Output

[1, 2, [3, 4]]
[1, 2, 3, 4]
3 4

append added one item, and that one item happened to be a whole list, so a has 3 items. extend added each of the two items, so b has 4. Lists inside lists come later; for now, notice the extra brackets and count them as one item.

One more pair trips people up: remove searches by value, while an index is a position.

nums = [5, 2, 9, 2]
nums.remove(2)
print(nums)

Output

[5, 9, 2]

remove(2) found the first item equal to 2, at index 1, and deleted it. The 9 at index 2 stayed, and so did the second 2.

Misconception check. Students often think nums = nums.sort() leaves a sorted list in nums, because it reads like "sort the numbers and keep them." That is tempting, because Week 7 taught you to store what a function hands back. But .sort() hands back None, so storing it throws the list away. The cure: call nums.sort() on its own line, or write nums = sorted(nums) when you want a new list.

In practice (your tools). Ask yourself before every method call: "does this hand back a thing, or None?" Then check in your browser runner by wrapping the call in print( ), as the first worked example did. The Standard Library reference, built-in functions, on docs.python.org, describes sorted().

Memory hook: pop hands back an item; the changers hand back None.

6. Aliases and copies: identity versus equality

A shared online document has one link. If you send the link to a friend and they fix a typo, you see the fix too, because there was only ever one document. A downloaded copy is different: their edits to it never reach yours. Lists behave like that shared link unless you ask for a copy.

An alias is a second name for the very same object, made by an assignment such as b = a, so a change made through either name shows up through the other.

A copy is a separate new list holding the same items as another, made with a full slice such as a[:], so later changes to one list leave the other untouched.

Worked example — alias against copy. This is the pinned program. Predict all seven lines.

a = [1, 2, 3]
b = a
b.append(4)
print(a)
print(b)
print(a is b)

a = [1, 2, 3]
b = a[:]
b.append(4)
print(a)
print(b)
print(a is b)
print(a == [1, 2, 3])

Output

[1, 2, 3, 4]
[1, 2, 3, 4]
True
[1, 2, 3]
[1, 2, 3, 4]
False
True

In the first half, b = a copied nothing. It gave the one list a second name, so the append through b shows up through a. In the second half, a[:] built a new list, so the append landed only in b.

is is the operator that gives True only when the names on both sides point at one and the same object, which is a stricter test than equal contents. == asks whether two values are equal; is asks whether they are the same object.

Worked example — equal but not the same. The pinned program builds two lists separately.

a = [1, 2]
b = [1, 2]
print(a == b)
print(a is b)
c = a
print(a is c)

Output

True
False
True

a and b hold equal items, so == says True, but they are two lists, so is says False. c = a made an alias, so a is c is True. In this course you compare values with == and save is for the question "is this the very same object?"

Here is the alias in an everyday setting, an illustrative team roster with a "backup" that is not a backup at all.

roster = ["Ana", "Kofi"]
backup = roster
roster.append("Mei")
print(backup)

Output

['Ana', 'Kofi', 'Mei']

The backup changed even though nobody touched it, because backup is an alias. With backup = roster[:] instead, the same program prints ['Ana', 'Kofi'].

Rebinding a name is a different move, and it does not reach through. In the pinned program x = 5, then y = x, then x = 10, and finally print(y), the output is 5. Giving x a new value points x somewhere new; it does not change the value y points at. Aliasing bites only when you change a list in place through one of its names.

Misconception check. Students often think b = a copies a list, because in Week 2 = seemed to put a value into a box. That is tempting, and for a number that you only ever rebind, the difference never shows. But a list can change in place, and then both names see the change. The cure: write b = a[:] whenever you want a separate list, and test with is when you are unsure.

In practice (your tools). Paste the alias-versus-copy program into Python Tutor at pythontutor.com and step through it. In the first half, watch two arrows from a and b point at one list box. In the second half, watch a second box appear when a[:] runs.

Memory hook: two names can share one list — a copy makes two.

7. The mutate-while-iterating trap: never edit the list you walk

Picture a teacher walking down a row of desks, tapping each one in turn. Halfway along, a student in the row stands up and leaves, and everyone behind slides one seat forward. The teacher, still stepping forward one desk at a time, now skips the student who slid into the empty seat. That is what happens when a loop walks a list that is shrinking under it.

The mutate-while-iterating trap is the bug that comes from adding or removing items in a list while a for loop is walking that same list, which makes the loop skip items; walking a copy or building a new list avoids it.

Worked example — the zero that got away. An illustrative practice log lists the minutes practiced on five days, and the program tries to remove every 0. Predict what prints.

minutes = [0, 0, 90, 0, 85]
for m in minutes:
    if m == 0:
        minutes.remove(0)
print(minutes)

Output

[90, 0, 85]

One 0 survived. Here is the trace.

  1. On the first pass the loop is at index 0, sees 0, and removes the first 0. Everything slides left, so the second 0 is now at index 0.
  2. On the second pass the loop moves on to index 1, which now holds 90. It never looked at the 0 that slid into index 0.
  3. On the third pass, at index 2, it sees the 0 that was once at index 3 and removes the first 0 in the list, which is the one at index 0. The list is now [90, 0, 85].
  4. There is no item at index 3 any more, so the loop ends with a 0 still inside.

The program ran without an error and printed the wrong list, so this is a logic error. The Python Tutorial's section 4.2 gives the same advice this section does: walk a copy, or build a new list.

Worked example — two cures. Each prints the list you wanted.

minutes = [0, 0, 90, 0, 85]
for m in minutes[:]:
    if m == 0:
        minutes.remove(0)
print(minutes)

Output

[90, 85]
minutes = [0, 0, 90, 0, 85]
kept = []
for m in minutes:
    if m != 0:
        kept.append(m)
print(kept)

Output

[90, 85]

The first cure walks minutes[:], a copy, so removing from the original never moves the items the loop is reading. The second cure never removes anything; it starts from an empty list and appends each item worth keeping.

Misconception check. Students often think a loop that removes each match removes every match. That is tempting, because the code says "for each item, if it is 0, remove a 0." But removal slides the later items left under the loop, so the loop skips one. The cure: never change the list you are walking; walk a copy, or build a new list.

In practice (your tools). Paste the trap into Python Tutor at pythontutor.com and step through it. Watch the list shrink after each removal, and watch which item m gets next. Then paste the copy cure and see the loop read every original item.

Memory hook: never edit the list your loop is walking.

8. Checking a chatbot: run the claim about a list

A friend tells you that the shared document link is a private copy. You do not argue; you open the link and check. A chatbot's claim about what a list program prints deserves the same treatment.

Worked example — "b = a makes a copy." Suppose you ask a chatbot how to back up a list before changing it, and it answers: "Write b = a. That makes a copy, so a stays [1, 2, 3]." Run the pinned program that tests exactly that claim.

a = [1, 2, 3]
b = a
b.append(4)
print(a)

Output

[1, 2, 3, 4]

The run printed [1, 2, 3, 4], so the claim was wrong: b = a made an alias, not a copy. The fix is the full slice from Section 6:

a = [1, 2, 3]
b = a[:]
b.append(4)
print(a)

Output

[1, 2, 3]

In words: the run caught a claim that sounded right, and the cure was one slice.

Misconception check. Students often think a chatbot's explanation is safe when it sounds sure of itself. That is tempting, because "that makes a copy" is a confident sentence. But a chatbot predicts likely text; it does not run your program. The cure: paste the code into your runner, compare what prints with what the chatbot said, and trust the run.

In practice (your tools). Ask your approved chatbot what print([5, 2, 9, 2].remove(2)) prints. Write down your own prediction first, then run it in your browser runner. The Python Tutorial's section 5.1 on docs.python.org says which list methods hand back None.

Honesty note: this chapter covers only the list tools Week 9 needs. Tuples, dictionaries, and sets arrive next week. Lists inside lists, the del statement, and deep copies come later. A full slice copies only the outer list; that limitation does not matter for lists of numbers and strings like the ones here.

Caveat: is happens to say True for some equal small numbers, because of a CPython detail. Never rely on it, and use == whenever you are comparing values.

Pause and choose one of these to think about before you read on:

  • (a) Think of a list you share with someone, such as a grocery list, a group chat's plan, or a team roster. Is it shared like an alias or like a copy, and what goes wrong when someone assumes the other?
  • (b) Think of a time you crossed items off a list while reading down it. Did you ever skip one, and how does that compare with the loop in Section 7?

Memory hook: trust the run, not the claim.

Key terms

  • list — An ordered collection of values kept under one name, written in square brackets with commas between the values, which a program can read by position and change after it is made. (first used: 1. Making a list: many values under one name)
  • item — One of the values stored in a list; each item sits at a numbered position, starting from 0 at the front. (first used: 1. Making a list: many values under one name)
  • empty list — A list with no items in it, written as a pair of square brackets with nothing between them, often used as the starting point for a list a loop will fill. (first used: 1. Making a list: many values under one name)
  • in place — Describes a change made to the existing list itself, so every name that points at that list sees the change, instead of a new list being built. (first used: 4. Changing a list: edits happen in place)
  • index assignment — A statement that puts a new value at one position of a list, written as the list name, the position in square brackets, an equals sign, and the new value. (first used: 4. Changing a list: edits happen in place)
  • method — A function that belongs to a value and is called with a dot after that value, such as append after a list name, so it can read or change that particular value. (first used: 4. Changing a list: edits happen in place)
  • append — The list method that adds one item to the end of a list in place and hands back None, even when the item it adds is itself a list. (first used: 4. Changing a list: edits happen in place)
  • insert — The list method that takes a position and an item, places the item at that position, shifts the later items one place to the right, and hands back None. (first used: 4. Changing a list: edits happen in place)
  • pop — The list method that removes an item, the last one or the one at the position given, and hands that removed item back to the code that called it. (first used: 4. Changing a list: edits happen in place)
  • remove — The list method that deletes the first item equal to the value it is given, searching by value rather than by position, and hands back None. (first used: 4. Changing a list: edits happen in place)
  • sort — The list method that rearranges a list into order in place and hands back None, so assigning what it hands back to a name stores None. (first used: 5. Return values: what each method hands back)
  • sorted() — The built-in function that builds and hands back a new list holding the items in order, leaving the original list exactly as it was. (first used: 5. Return values: what each method hands back)
  • extend — The list method that adds every item of another list, one by one, to the end of a list in place and hands back None. (first used: 5. Return values: what each method hands back)
  • alias — A second name for the very same object, made by an assignment such as b = a, so a change made through either name shows up through the other. (first used: 6. Aliases and copies: identity versus equality)
  • copy — A separate new list holding the same items as another, made with a full slice such as a[:], so later changes to one list leave the other untouched. (first used: 6. Aliases and copies: identity versus equality)
  • is — The operator that gives True only when the names on both sides point at one and the same object, which is a stricter test than equal contents. (first used: 6. Aliases and copies: identity versus equality)
  • mutate-while-iterating trap — The bug that comes from adding or removing items in a list while a for loop is walking that same list, which makes the loop skip items; walking a copy or building a new list avoids it. (first used: 7. The mutate-while-iterating trap: never edit the list you walk)

Summary

  • A list keeps many values, in order, under one name.
  • Index from 0 at the front or from -1 at the back.
  • An index past the end raises IndexError.
  • A slice is a new list; changing it leaves the original alone.
  • A total starts at 0; a biggest-so-far starts at the first item.
  • pop hands back an item; append, insert, remove, and sort hand back None.
  • sorted() makes a new list; .sort() changes the list and returns None.
  • b = a makes an alias; b = a[:] makes a copy.
  • Never remove items from the list your loop is walking.

Check your understanding

Work these before looking at the answers — they are ungraded, and the answers (with reasoning) are at the bottom of the page.

  1. A bookshop app stores shelf numbers as shelf = [7, 14, 21, 28, 35] (an illustrative example). Predict shelf[1:4] and shelf[-2].
  2. An illustrative bike-share report lists the bikes at four docks: docks = [6, 9, 4, 11]. A program totals them, prints the total divided by len(docks), and finds the biggest dock with a biggest-so-far that starts at docks[0]. Predict the three printed values.
  3. A design app runs colors = ["red", "blue"], then extra = colors, then extra.append("green"), then print(len(colors)). Predict the output and explain it in one sentence.
  4. A dice game stores rolls = [3, 6, 2] and then runs rolls = rolls.sort() and print(rolls). Predict the output, and give two ways to fix the program so it prints the sorted rolls.

Answers (worked reasoning — read after attempting)

  1. shelf[1:4] is [14, 21, 28]: it starts at index 1 and stops before index 4, so it takes indexes 1, 2, and 3, which is 4 − 1 = 3 items. shelf[-2] counts back from the end: −1 is 35, so −2 is 28.
  2. The total is 6 + 9 + 4 + 11 = 30. The average is 30 ÷ 4 = 7.5, printed as a float because / always gives one. The biggest starts at 6, is replaced by 9, stays at 9 for the 4, and is replaced by 11, so it prints 11.
  3. It prints 3. extra = colors made an alias, not a copy, so the append through extra changed the one list both names point at. This is the "b = a copies" trap; extra = colors[:] would have left colors with 2 items.
  4. It prints None. rolls.sort() sorts the list in place and hands back None, and the assignment stores that None in rolls. Fix it by writing rolls.sort() on a line of its own, or by writing rolls = sorted(rolls); either way the program prints [2, 3, 6].

Next up in this module: the Readings & Resources page, the lecture tutorial, the practice set, and the quiz — and next week, dictionaries bring a new method of lookup: finding a value by its name instead of its position, following the same rule of in-place change you met here.

Built with The Course Maker · samples.thecoursemaker.com