Lists
A list is an ordered, changeable collection that may hold duplicates and mixed types.
marks = [78, 92, 65, 92]
mixed = [1, "two", 3.0, True]
empty = []
Indexing and slicing
marks[0] # 78 first
marks[-1] # 92 last
marks[1:3] # [92, 65] end excluded, as with range
marks[:2] # [78, 92] from the start
marks[2:] # [65, 92] to the end
marks[::-1] # [92, 65, 92, 78] reversed
An index out of range raises IndexError. A slice out of range does
not — it just gives you what exists. That asymmetry surprises people:
marks[10] # IndexError
marks[10:20] # [] no error
Lists are mutable
marks[0] = 80 # change in place
marks.append(55) # add to the end
marks.insert(1, 99) # insert at position
marks.remove(92) # remove the FIRST 92 only
popped = marks.pop() # remove and return the last
del marks[0] # delete by index
remove() removing only the first match is worth remembering — with
duplicates it does not do what many students expect.
Useful operations
len(marks) sum(marks) max(marks) min(marks)
sorted(marks) # NEW sorted list, original untouched
marks.sort() # sorts IN PLACE, returns None
marks.reverse() # in place
marks.count(92) # how many times 92 appears
marks.index(65) # position of first 65
92 in marks # True/False membership
sorted() versus .sort() is a common exam point:
new = sorted(marks) # new is the sorted list
new = marks.sort() # new is None — a classic bug
Anything that mutates in place tends to return None in Python. It is a
deliberate signal: "I changed the thing, I did not make you a new one."
The reference trap
This is the most important idea in the topic.
a = [1, 2, 3]
b = a # b refers to the SAME list
b.append(4)
print(a) # [1, 2, 3, 4] — a changed too
b = a does not copy. Both names point at one list, so changing it
through either name changes what both see. To copy:
b = a.copy() # or a[:] or list(a)
b.append(4)
print(a) # [1, 2, 3] unchanged
This connects to Module 1's point that a Python variable is a name for an object, not a box holding a value.
Building lists in a loop
squares = []
for i in range(1, 6):
squares.append(i * i) # [1, 4, 9, 16, 25]
Or as a comprehension, which you will meet in reading even if the syllabus does not require you to write them:
squares = [i * i for i in range(1, 6)]
Don't modify a list while iterating it
for x in numbers:
if x < 0:
numbers.remove(x) # skips elements — silently wrong
Removing shifts everything left while the loop's internal index keeps advancing, so items get skipped. Build a new list instead:
numbers = [x for x in numbers if x >= 0]