list: Creating, Accessing, Adding, Removing, Searching and Looping
- Create a list and access items by positive and negative index
- Add and remove items with append, insert, remove, pop and del
- Search a list with in, index and count
- Loop over a list, including with enumerate, and sort it
What will we learn?
list is the most common data structure in Python. We already used it briefly. Today we will learn it properly:
- Creating it and accessing items.
- Adding, removing and changing.
- Searching.
- Looping and sorting.
Why do we need this?
Almost every program holds collections: a list of students, products in a cart, today’s orders, lines from a file, results of a Database query (the backend and databases topics). When the number is not known in advance, you cannot keep a separate variable for each item (student1, student2…). A list holds as many as needed, in a certain order.
Explanation from the basics
What is a list?
A list is an ordered collection of values:
- Ordered — every item has a fixed position, the index.
- Mutable — you can add, remove and change items after it is created.
- Allows duplicates — the same value can appear several times.
- Any type — you can mix them (
[1, "a", True]), but usually a list holds items of the same kind.
A list is a train with numbered cars. Every car (item) carries a load (a value). The first car is number 0, not 1. You can attach a car at the end (append), put a car in the middle (insert), or detach a car (remove/pop).
Indexes
fruits = ["apple", "banana", "cherry", "date"]
index: 0 1 2 3
negative: -4 -3 -2 -1- Counting starts from 0.
- A negative index counts from the end:
-1= the last one,-2= the one before last. - An index that does not exist →
IndexError.
Syntax
# create
empty = []
numbers = [10, 20, 30]
# access and change
numbers[0] # 10 - first item
numbers[-1] # 30 - last item
numbers[1] = 25 # change an item
len(numbers) # 3 - how many items
# add
numbers.append(40) # add to the end
numbers.insert(0, 5) # insert at index 0, pushing the rest right
# remove
numbers.remove(25) # remove the FIRST item equal to 25
last = numbers.pop() # remove and return the last item
first = numbers.pop(0) # remove and return the item at index 0
del numbers[0] # delete by index (returns nothing)
numbers.clear() # remove everything
# search
30 in numbers # True / False
numbers.index(30) # index of the first 30 (ValueError if missing)
numbers.count(30) # how many times 30 appears
# sort
numbers.sort() # sorts THIS list in place
numbers.sort(reverse=True) # descending
sorted(numbers) # returns a NEW sorted list, original unchangedA method is a function that “belongs” to an object, and is called with a dot: numbers.append(40). We will learn about methods in depth in the OOP topic. For now: “an action the list knows how to do on itself”.
First code example
week-2/shopping_list.py:
shopping = ["milk", "bread", "eggs"]
print("Start:", shopping)
shopping.append("cheese")
print("After append:", shopping)
shopping.insert(1, "butter")
print("After insert:", shopping)
shopping.remove("bread")
print("After remove:", shopping)
print("First item:", shopping[0])
print("Last item:", shopping[-1])
print("Items count:", len(shopping))Output:
Start: ['milk', 'bread', 'eggs']
After append: ['milk', 'bread', 'eggs', 'cheese']
After insert: ['milk', 'butter', 'bread', 'eggs', 'cheese']
After remove: ['milk', 'butter', 'eggs', 'cheese']
First item: milk
Last item: cheese
Items count: 4Breaking down the code line by line
| Line | What happened to the list |
|---|---|
shopping = [...] | Created with 3 items: indexes 0, 1, 2. |
.append("cheese") | Added at the end. Now 4 items. |
.insert(1, "butter") | Went in at index 1. What was there (bread) and what came after it moved right. |
.remove("bread") | Removed by value: Python looks for the first occurrence of "bread" and removes it. |
shopping[0] | The first item. |
shopping[-1] | The last item, without knowing how many there are. |
len(shopping) | The number of items. |
Notice: append, insert and remove change the list itself and do not return a new list. That is why you do not write shopping = shopping.append(...) (more on that in the mistakes section).
Another example
Managing a checkout queue: looping, searching, pop and enumerate. week-2/queue.py:
queue = ["dana", "avi", "noa", "avi", "yossi"]
print("People in queue:", len(queue))
print("Is noa waiting?", "noa" in queue)
print("noa's position:", queue.index("noa") + 1)
print("How many times avi:", queue.count("avi"))
served = queue.pop(0)
print("Now serving:", served)
print("--- Remaining queue ---")
for position, name in enumerate(queue, start=1):
print(position, name)
queue.sort()
print("Alphabetical:", queue)Output:
People in queue: 5
Is noa waiting? True
noa's position: 3
How many times avi: 2
Now serving: dana
--- Remaining queue ---
1 avi
2 noa
3 avi
4 yossi
Alphabetical: ['avi', 'avi', 'noa', 'yossi']Breakdown:
"noa" in queue—ingoes over the list and checks whether the value exists. It returns abool.queue.index("noa") + 1—indexreturns the index (2). We add 1 because for people, “third place” starts from 1.queue.pop(0)— takes out and returns the first one. That is the difference fromremove:popgives you the value that was taken out, so we can use it (served).enumerate(queue, start=1)— in every round it gives a pair: a running number and the item.for position, name in ...unpacks the pair into two variables. Withoutstart=1, counting starts from 0.queue.sort()— sorts the list itself, alphabetically for text and in ascending order for numbers.
Common mistake
Mistake 1: assigning the result of a method that changes the list in place.
names = ["noa", "avi"]
names = names.append("dana")
print(names)Noneappend changes the list and returns None. We assigned the None into names, and lost the list! The fix: names.append("dana") on its own. The same goes for sort(), insert(), remove().
Mistake 2: Off-by-one on the last index.
items = ["a", "b", "c"]
print(items[len(items)])IndexError: list index out of rangelen is 3, but the last index is 2. The last one = items[-1] or items[len(items) - 1].
Mistake 3: remove on a value that does not exist.
items.remove("z")ValueError: list.remove(x): x not in listCheck first: if "z" in items: items.remove("z").
Mistake 4: removing from a list while looping over it.
numbers = [1, 2, 2, 3]
for n in numbers:
if n == 2:
numbers.remove(n)
print(numbers)[1, 2, 3]We expected [1, 3]. When you remove an item, all the items move left, and the loop “skips” the next item. The safe solution: build a new list with what you want to keep:
numbers = [1, 2, 2, 3]
kept = []
for n in numbers:
if n != 2:
kept.append(n)
print(kept) # [1, 3]Practice
The exercises use only what was taught in this lesson and the lessons before it. Try on your own first, and only then open the solution.
Exercise 1: Indexes
days = ["Sun", "Mon", "Tue", "Wed", "Thu"]Print, using indexes only: the first day, the last day (with a negative index), and the middle day.
Expected output:
Sun
Thu
TueShow solution
days = ["Sun", "Mon", "Tue", "Wed", "Thu"]
print(days[0])
print(days[-1])
print(days[2])Sun
Thu
TueIndexes start from 0. A negative index counts from the end: -1 is the last item.
Exercise 2: A shopping list
Start from ["milk", "bread"], and do the following in order:
- Add
"eggs"to the end. - Add
"butter"in the first place. - Remove
"bread". - Print the list and the number of items.
Expected output:
['butter', 'milk', 'eggs']
3Show solution
shopping = ["milk", "bread"]
shopping.append("eggs")
shopping.insert(0, "butter")
shopping.remove("bread")
print(shopping)
print(len(shopping))['butter', 'milk', 'eggs']
3append— to the end.insert(0, ...)— to a specific position.remove— removes by value (the first occurrence).
Exercise 3: A queue
queue = ["dana", "avi", "noa", "avi", "yossi"]- Check whether
"noa"is in the queue, and print which place she is in (the first place is 1). - Print how many times
"avi"appears. - Take out the first person in the queue and print
Now serving: <name>, and the number of people who remain.
Expected output:
True
3
2
Now serving: dana
4Show solution
queue = ["dana", "avi", "noa", "avi", "yossi"]
print("noa" in queue)
print(queue.index("noa") + 1)
print(queue.count("avi"))
served = queue.pop(0)
print("Now serving:", served)
print(len(queue))True
3
2
Now serving: dana
4pop(0) both removes and returns the item — that is why you can save it in a variable.
Exercise 4: Statistics on grades
grades = [78, 92, 55, 88, 100, 43, 67]Print the highest grade, the lowest, the average (rounded to one digit), and a new list of the grades that passed (55 and above) — without changing grades.
Expected output:
Highest: 100
Lowest: 43
Average: 74.7
Passed: [78, 92, 55, 88, 100, 67]Show solution
PASSING_GRADE = 55
grades = [78, 92, 55, 88, 100, 43, 67]
print("Highest:", max(grades))
print("Lowest:", min(grades))
print("Average:", round(sum(grades) / len(grades), 1))
passed = []
for grade in grades:
if grade >= PASSING_GRADE:
passed.append(grade)
print("Passed:", passed)Highest: 100
Lowest: 43
Average: 74.7
Passed: [78, 92, 55, 88, 100, 67]The pattern of “a new list + a loop + append” is the way to filter a list without touching the original.
Exercise 5: Removing during a loop
numbers = [1, 2, 2, 3, 2, 4]
for n in numbers:
if n == 2:
numbers.remove(n)
print(numbers)The intention was to remove all the 2s, but one remained. Write a function remove_all(items, value) that returns a new list without any occurrence of value.
Expected output:
[1, 3, 4]Show solution
When you remove from a list while looping over it, the items move left, and the loop skips the item that moved into the removed place. That is why you build a new list instead:
def remove_all(items, value):
result = []
for item in items:
if item != value:
result.append(item)
return result
print(remove_all([1, 2, 2, 3, 2, 4], 2))[1, 3, 4]Summary
- list = an ordered, mutable collection, with duplicates. Written with
[ ]. - An index starts at 0.
-1= the last one. An index that does not exist →IndexError. - Adding:
append(to the end),insert(to a position). Removing:remove(by value),pop(by position, and it returns the item),del. - Searching:
in,index,count. Looping:for, andenumeratewhen you also need a number. - Methods that change in place (
append,sort…) returnNone.sorted()returns a new list. - Do not remove from a list while looping over it. Build a new list.