Lists & Tuples
tuple — what makes it different, when to use it, and how packing/unpacking works.
Lists vs Tuples at a Glance
Both lists and tuples store ordered sequences of items and support indexing, slicing, and for loops. The key difference is mutability: lists can be changed after creation; tuples cannot.
- Mutable — items can be added, removed, changed
- Ordered — items keep their insertion order
- Allows duplicate values
- Use for collections that change: shopping cart, student marks, to-do items
- Has many built-in methods (.append, .sort, .pop…)
- Immutable — cannot be changed after creation
- Ordered — items keep their insertion order
- Allows duplicate values
- Use for fixed data: coordinates, RGB colours, database rows
- Slightly faster and uses less memory than list
Creating & Accessing Lists
A list is created with square brackets [ ]. Items can be of any type — even mixed types or other lists. Access items with an index (0-based), and use negative indexes to count from the end — exactly like strings.
# Creating lists fruits = ["apple", "banana", "mango", "grape"] marks = [85, 92, 78, 95, 88] mixed = ["Ali", 21, True, 3.14] # any types allowed empty = [] # empty list nested = [[1,2], [3,4], [5,6]] # list of lists # Indexing (0-based) print(fruits[0]) # apple (first) print(fruits[2]) # mango print(fruits[-1]) # grape (last) print(fruits[-2]) # mango (second from last) # Slicing — same as strings print(fruits[1:3]) # ['banana', 'mango'] print(fruits[:2]) # ['apple', 'banana'] print(fruits[::-1]) # reversed list # Modify an item (lists are mutable!) fruits[1] = "blueberry" print(fruits) # ['apple', 'blueberry', 'mango', 'grape'] # Length and membership print(len(fruits)) # 4 print("mango" in fruits) # True # Nested list access print(nested[1][0]) # 3 (second list, first element)
Essential List Methods
Lists come with powerful built-in methods. These are called with dot notation: list.method(). Unlike string methods, most list methods modify the list in-place and return None — they don't create a new list.
| Method | Description | Returns | Example |
|---|---|---|---|
| .append(x) | Add x to the end | None | lst.append(5) |
| .insert(i, x) | Insert x at index i | None | lst.insert(0, "first") |
| .extend(iter) | Add all items from iterable | None | lst.extend([4,5,6]) |
| .remove(x) | Remove first occurrence of x | None | lst.remove("apple") |
| .pop(i) | Remove & return item at index i (default: last) | item | last = lst.pop() |
| .sort() | Sort in-place (ascending by default) | None | lst.sort(reverse=True) |
| .reverse() | Reverse the list in-place | None | lst.reverse() |
| .index(x) | Return index of first occurrence of x | int | lst.index("mango") |
| .count(x) | Count occurrences of x | int | lst.count(5) |
| .copy() | Return a shallow copy | list | b = lst.copy() |
| .clear() | Remove all items | None | lst.clear() |
students = ["Ali", "Sara", "Zara"] students.append("Omar") # add to end students.insert(1, "Bilal") # insert at index 1 print(students) # ['Ali', 'Bilal', 'Sara', 'Zara', 'Omar'] students.remove("Zara") # remove by value last = students.pop() # remove last, return it print(f"Removed: {last}") # Omar students.sort() # alphabetical sort print(students) # ['Ali', 'Bilal', 'Sara'] # sorted() — returns NEW sorted list, original unchanged marks = [72, 95, 61, 88] ranked = sorted(marks, reverse=True) print(ranked) # [95, 88, 72, 61] print(marks) # [72, 95, 61, 88] — unchanged! # Built-in functions on lists print(sum(marks)) # 316 print(max(marks)) # 95 print(min(marks)) # 61 print(len(marks)) # 4
marks.sort() permanently reorders the original list and returns None. sorted(marks) leaves the original unchanged and returns a brand-new sorted list. Use sorted() when you need to keep the original order — which is almost always the safer choice.List Comprehensions
A list comprehension is Python's most elegant feature for creating lists. It collapses a loop-and-append pattern into a single, readable line. Once you learn it, you'll use it everywhere.
# Old way: loop + append squares = [] for i in range(1, 6): squares.append(i ** 2) # Comprehension — same result, one line squares = [i ** 2 for i in range(1, 6)] print(squares) # [1, 4, 9, 16, 25] # With a filter condition evens = [x for x in range(1, 11) if x % 2 == 0] print(evens) # [2, 4, 6, 8, 10] # Transform strings names = [" ali ", " SARA ", "zara"] clean = [n.strip().title() for n in names] print(clean) # ['Ali', 'Sara', 'Zara'] # Filter + transform: passing marks only marks = [55, 42, 88, 31, 76, 90] passed = [m for m in marks if m >= 50] print(passed) # [55, 88, 76, 90] # Ternary inside comprehension grades = ["Pass" if m >= 50 else "Fail" for m in marks] print(grades) # ['Pass', 'Fail', 'Pass', 'Fail', 'Pass', 'Pass'] # Flatten a nested list matrix = [[1,2],[3,4],[5,6]] flat = [n for row in matrix for n in row] print(flat) # [1, 2, 3, 4, 5, 6]
Tuples — Immutable Sequences
Tuples are created with parentheses ( ) or just commas. They support indexing, slicing, and for loops exactly like lists — but you cannot add, remove, or change their items after creation.
# Creating tuples point = (3, 7) # 2D coordinate rgb = (255, 128, 0) # orange colour person = ("Ali", 22, "Lahore") single = (42,) # MUST have trailing comma for single item! packed = 1, 2, 3 # parentheses optional (packing) # Indexing and slicing — same as list print(rgb[0]) # 255 print(rgb[-1]) # 0 print(rgb[:2]) # (255, 128) # Attempting to modify raises TypeError # rgb[0] = 200 ← TypeError: 'tuple' object does not support item assignment # Tuple unpacking — assign all values in one line name, age, city = person print(name, age, city) # Ali 22 Lahore # Swap variables using tuple packing/unpacking a, b = 10, 20 a, b = b, a print(a, b) # 20 10 # Extended unpacking with * first, *rest = (1, 2, 3, 4, 5) print(first) # 1 print(rest) # [2, 3, 4, 5] *head, last = (1, 2, 3, 4, 5) print(last) # 5
return name, age, it's really returning a single tuple (name, age). When you write n, a = get_info() you're tuple-unpacking. This is why tuple unpacking is one of the most important Python patterns to master.Practical Patterns
.append(x) to push, .pop() to pull from the top. Stacks power undo systems, call stacks, and expression parsers..append(x) to enqueue, .pop(0) to dequeue from the front. For performance, use collections.deque instead.list(zip([1,2,3], ["a","b","c"])) → [(1,"a"), (2,"b"), (3,"c")]. Combine two parallel lists into pairs.b = a makes b point to the SAME list. Use b = a.copy() or b = a[:] for an independent copy. Otherwise changing b also changes a.# ── Stack (undo history) ───────────────────── history = [] history.append("typed 'hello'") history.append("deleted word") history.append("pasted image") last_action = history.pop() print(f"Undone: {last_action}") # Undone: pasted image # ── Copy trap ──────────────────────────────── a = [1, 2, 3] b = a # b IS a — same object! b.append(4) print(a) # [1, 2, 3, 4] ← a was changed too! a = [1, 2, 3] b = a.copy() # independent copy b.append(4) print(a) # [1, 2, 3] ← a is safe # ── Tuple as function "return multiple values" ─ def min_max(nums): return min(nums), max(nums) # returns a tuple lo, hi = min_max([8, 3, 15, 1, 9]) print(lo, hi) # 1 15 # ── Convert between list and tuple ─────────── t = (1, 2, 3) l = list(t) # tuple → list (now mutable) l.append(4) t = tuple(l) # list → tuple (now immutable again) print(t) # (1, 2, 3, 4)
[x**2 for x in range(4)] produce?b = a where a = [1,2,3], if you do b.append(4), what is a?.pop() do with no argument?42?1. Asks the user to enter 5 student names and their marks (use two lists built with a
while loop)2. Uses
zip() to pair names and marks, then stores as a list of tuples3. Uses a list comprehension to extract only passing students (mark ≥ 50)
4. Sorts the full list by mark descending using
sorted() with a key argument5. Unpacks each tuple to print a ranked leaderboard with position, name, mark, and grade
6. Calculates and prints the class average, highest, and lowest mark
💡 Show hints
- Store as tuples:
records = list(zip(names, marks)) - Sort by mark:
sorted(records, key=lambda x: x[1], reverse=True) - Unpack in loop:
for pos, (name, mark) in enumerate(ranked, 1): - Grade ternary:
"A" if mark >= 80 else "B" if mark >= 65 else "C" if mark >= 50 else "F"
# ── Student Marks Manager ───────────────────── names = []; marks = [] print("Enter 5 students (name then mark):\n") while len(names) < 5: n = input(f" Student {len(names)+1} name : ").strip().title() m = int(input(f" {n}'s mark (0-100): ")) names.append(n); marks.append(m) records = list(zip(names, marks)) passing = [r for r in records if r[1] >= 50] ranked = sorted(records, key=lambda x: x[1], reverse=True) def grade(m): return "A" if m>=80 else "B" if m>=65 else "C" if m>=50 else "F" print(f"\n{'═'*40}") print(" 🏆 LEADERBOARD") print(f"{'─'*40}") for pos, (name, mark) in enumerate(ranked, 1): print(f" {pos}. {name:12} {mark:3} Grade: {grade(mark)}") print(f"{'─'*40}") print(f" Average : {sum(marks)/len(marks):.1f}") print(f" Highest : {max(marks)}") print(f" Lowest : {min(marks)}") print(f" Passing : {len(passing)}/{len(records)}") print(f"{'═'*40}")