Lists and Tuples · Lesson 16 of 39
Lists
A list holds many values in order: a shopping list, the marks of a class, the messages in a chat. It is the collection you will use most in Python, so this lesson covers it properly – including the copying trap that catches nearly every beginner.
In this lesson
- Creating lists, indexing and slicing
- Adding, removing and changing items
sort()versussorted(), and sorting by a key- Copying lists safely and working with lists of lists
Creating a list
marks = [78, 92, 65, 88]
names = ["Asha", "Ben", "Chitra"]
mixed = [1, "two", 3.0, True, None] # allowed, but usually a bad idea
empty = []
print(marks)
print(len(names), len(empty))
[78, 92, 65, 88] 3 0
Lists use square brackets and commas. Indexing and slicing work exactly like strings:
marks = [78, 92, 65, 88]
- 780-4
- 921-3
- 652-2
- 883-1
marks = [78, 92, 65, 88]
print(marks[0], marks[-1])
print(marks[1:3])
print(marks[::-1])
78 88 [92, 65] [88, 65, 92, 78]
Lists are mutable
Unlike strings, you can change a list in place:
tasks = ["email", "report", "call"]
tasks[1] = "presentation"
print(tasks)
['email', 'presentation', 'call']
Adding items
cart = ["rice"]
cart.append("dal") # one item at the end
cart.insert(0, "oil") # at a position
cart.extend(["salt", "sugar"]) # many items at the end
print(cart)
['oil', 'rice', 'dal', 'salt', 'sugar']
Common mistake: append vs extend
cart.append(["salt", "sugar"]) adds one item – a list inside the list: [..., ['salt', 'sugar']]. Use extend (or +=) to add each item separately.
Removing items
queue = ["Arun", "Bela", "Chris", "Bela", "Dev"]
queue.remove("Bela") # first matching value
print(queue)
last = queue.pop() # remove and return the last item
first = queue.pop(0) # remove and return by index
print(first, last, queue)
del queue[0] # delete by index
print(queue)
queue.clear()
print(queue)
['Arun', 'Chris', 'Bela', 'Dev'] Arun Dev ['Chris', 'Bela'] ['Bela'] []
| Method | Removes by | Returns | Missing item |
|---|---|---|---|
remove(x) | value (first match) | None | ValueError |
pop(i) | index (default: last) | the item | IndexError |
del lst[i] | index or slice | – | IndexError |
clear() | everything | None | – |
Searching and counting
rolls = [4, 6, 2, 6, 1, 6]
print(6 in rolls)
print(rolls.count(6))
print(rolls.index(2))
print(min(rolls), max(rolls), sum(rolls))
True 3 2 1 6 25
Sorting: sort() or sorted()?
list.sort() sorts the list in place and returns None. sorted(any_iterable) leaves the original alone and returns a new list.
scores = [70, 95, 82, 60]
ranked = sorted(scores, reverse=True)
print(ranked, scores) # original unchanged
scores.sort()
print(scores)
result = scores.sort()
print(result) # sort() returns None!
[95, 82, 70, 60] [70, 95, 82, 60] [60, 70, 82, 95] None
Sorting with a key
Pass key= a function that says what to sort by:
words = ["banana", "Kiwi", "apple", "fig"]
print(sorted(words)) # capitals first
print(sorted(words, key=str.lower)) # alphabetical, ignoring case
print(sorted(words, key=len)) # by length
students = [("Ria", 88), ("Om", 95), ("Lata", 72)]
print(sorted(students, key=lambda s: s[1], reverse=True))
['Kiwi', 'apple', 'banana', 'fig']
['apple', 'banana', 'fig', 'Kiwi']
['fig', 'Kiwi', 'apple', 'banana']
[('Om', 95), ('Ria', 88), ('Lata', 72)]lambda s: s[1] is a tiny unnamed function meaning "give me the second element". You will meet lambdas properly in chapter 9.
Copying a list
Remember from the Variables lesson: b = a does not copy. Both names point at the same list.
original = [1, 2, 3]
alias = original
copy1 = original.copy()
copy2 = original[:]
copy3 = list(original)
original.append(4)
print(alias)
print(copy1, copy2, copy3)
[1, 2, 3, 4] [1, 2, 3] [1, 2, 3] [1, 2, 3]
Alias or copy?
Do you need an independent list?
- No – same list, another name
b = a - Yes – flat list
a.copy(),a[:]orlist(a)(shallow copy) - Yes – lists inside lists
copy.deepcopy(a)
A shallow copy duplicates the outer list only. If the items are themselves lists, they are still shared:
import copy
grid = [[0, 0], [0, 0]]
shallow = grid.copy()
deep = copy.deepcopy(grid)
grid[0][0] = 9
print(shallow) # inner list is shared
print(deep) # fully independent
[[9, 0], [0, 0]] [[0, 0], [0, 0]]
Lists of lists (2-D data)
sales = [
["Jan", 120, 90],
["Feb", 150, 110],
["Mar", 170, 95],
]
for month, online, store in sales:
print(f"{month}: total {online + store}")
print("Feb online:", sales[1][1])
Jan: total 210 Feb: total 260 Mar: total 265 Feb online: 150
Common mistake: [[0] * 3] * 3
This creates one inner list repeated three times, so changing board[0][0] changes every row. Build grids with a comprehension instead: [[0] * 3 for _ in range(3)] (next lesson).
Practice
Try it yourself
Remove duplicates from
[3, 1, 3, 2, 1, 5]while keeping the original order.Show solution
nums = [3, 1, 3, 2, 1, 5] unique = [] for n in nums: if n not in unique: unique.append(n) print(unique) print(list(dict.fromkeys(nums))) # a shorter trick[3, 1, 2, 5] [3, 1, 2, 5]
Find the second largest number in
[12, 45, 7, 45, 30].Show solution
nums = [12, 45, 7, 45, 30] distinct = sorted(set(nums), reverse=True) print(distinct[1])30
Rotate
[1, 2, 3, 4, 5]left by two places →[3, 4, 5, 1, 2].Show solution
nums = [1, 2, 3, 4, 5] k = 2 print(nums[k:] + nums[:k])[3, 4, 5, 1, 2]
Quick check
What does nums.sort() return?
None. It sorts the list in place; use sorted(nums) for a new list.
After b = a[:], does b.append(1) change a?
No – a[:] creates a (shallow) copy.
What is the difference between remove() and pop()?
remove(x) deletes the first item equal to x; pop(i) deletes the item at index i (last by default) and returns it.
Summary
- Lists are ordered and mutable; index and slice them like strings.
- Add with
append/insert/extend; remove withremove/pop/del. sort()changes the list and returns None;sorted()returns a new list; both acceptkeyandreverse.- Copy with
.copy(), usecopy.deepcopy()for nested lists.
Finished this lesson?
Mark it complete to track your progress, then carry on with the next lesson.