C.W.K.
Stream
Lesson 02 of 07 · published

List Methods & Mutation Patterns — append vs extend, sort vs sorted

~22 min · list, mutation, append, extend, sort

Level 0Curious
0 XP0/93 lessons0/23 achievements
0/100 XP to next level100 XP to go0% complete

The two append families — and why they're not interchangeable

Two of the most-used methods on lists are append and extend, and they look similar enough that beginners use them interchangeably and then get confused. append(x) adds one element to the end. extend(iterable) adds each element of an iterable one by one. Pass a string to extend and you'll get every character — almost never what you wanted.

Insert, remove, pop — surgical mutations

insert(i, x) puts x at position i, pushing later elements right. remove(x) removes the first occurrence of value x — raises ValueError if it's not there. pop(i) removes and returns the element at index i (default: last). The fact that pop returns the removed value is what makes lists usable as a stack with no extra structure.

The sort/sorted distinction — in-place vs. return

Python has two ways to sort, and they don't mean the same thing. my_list.sort() sorts in place and returns None. sorted(iterable) returns a new sorted list and leaves the input alone. The second works on any iterable, not just lists. The first is a tiny bit faster and uses less memory, but it changes your data.

Principle: Methods that mutate in place return None. my_list.sort(), my_list.reverse(), my_list.append(x) — all return None. The most common bug from this: x = my_list.sort() and then being confused why x is None. Want a sorted copy? Use sorted(my_list).

The key argument — sorting on something other than the value

Both sort and sorted take an optional key function. The list isn't sorted by the elements themselves — it's sorted by what key returns when called on each element. key=str.lower for case-insensitive string sorting. key=len to sort by length. key=lambda x: x["age"] to sort dicts by a field. This pattern shows up everywhere.

List as stack vs list as queue

A list works fine as a stack: append to push, pop to pop. Both are O(1). But as a queue, lists are awful: pop(0) from the left is O(n) because every element has to shift. If you want a queue, use collections.deque (we cover it in the stdlib track).

Pythonic Way: Don't loop and call append when you can build the list with a comprehension. [x*2 for x in source] beats a five-line for-loop nine times out of ten. We get to comprehensions in lesson 6.

Code

append vs extend — the one beginners trip on·python
letters = ['a', 'b']

# append: adds ONE element (even if that element is itself a list)
letters.append(['c', 'd'])
print(letters)              # ['a', 'b', ['c', 'd']]

letters = ['a', 'b']
# extend: adds EACH element from the iterable
letters.extend(['c', 'd'])
print(letters)              # ['a', 'b', 'c', 'd']

# Watch out — strings are iterable
letters = ['a', 'b']
letters.extend("cd")
print(letters)              # ['a', 'b', 'c', 'd']  — characters!

# Equivalent: my_list += other_iterable
letters = ['a', 'b']
letters += ['c', 'd']
print(letters)              # ['a', 'b', 'c', 'd']
remove, pop, insert, del — the rest of the surgery kit·python
items = ['a', 'b', 'c', 'b', 'd']

# remove the FIRST occurrence of a value
items.remove('b')
print(items)                # ['a', 'c', 'b', 'd']

# pop returns AND removes — perfect for a stack
last = items.pop()
print(last, items)          # 'd' ['a', 'c', 'b']

first = items.pop(0)
print(first, items)         # 'a' ['c', 'b']

# insert at a specific index
items.insert(0, 'X')
print(items)                # ['X', 'c', 'b']

# del removes by index without returning
del items[1]
print(items)                # ['X', 'b']

# del a slice — remove a range
del items[:]
print(items)                # []
sort vs sorted — the one that returns None·python
nums = [3, 1, 4, 1, 5, 9, 2, 6]

# sort — IN PLACE, returns None
result = nums.sort()
print(result)               # None    <- common bug source
print(nums)                 # [1, 1, 2, 3, 4, 5, 6, 9]

# sorted — returns a NEW list, original untouched
nums = [3, 1, 4, 1, 5]
new = sorted(nums)
print(new)                  # [1, 1, 3, 4, 5]
print(nums)                 # [3, 1, 4, 1, 5]   unchanged

# Reversed sort
print(sorted(nums, reverse=True))   # [5, 4, 3, 1, 1]
The key argument — sort on something derived·python
words = ["banana", "Apple", "cherry", "date"]

# Default sort is case-sensitive — 'A' < 'b'
print(sorted(words))                  # ['Apple', 'banana', 'cherry', 'date']

# key=str.lower lowercases each element BEFORE comparing
print(sorted(words, key=str.lower))   # ['Apple', 'banana', 'cherry', 'date']

# Sort by length
print(sorted(words, key=len))         # ['date', 'Apple', 'banana', 'cherry']

# Sort dicts by a field
people = [{"name": "A", "age": 30},
          {"name": "B", "age": 25},
          {"name": "C", "age": 35}]
print(sorted(people, key=lambda p: p["age"]))
# [{'name': 'B', 'age': 25}, {'name': 'A', 'age': 30}, {'name': 'C', 'age': 35}]
Why list is a bad queue (and deque is the answer)·python
# As a stack — fast, O(1) on both ends
stack = []
stack.append(1)        # push    O(1)
stack.append(2)
stack.pop()            # pop     O(1)

# As a queue from the LEFT — SLOW, O(n)
queue = [1, 2, 3, 4]
queue.pop(0)           # O(n) — every element shifts left

# Use collections.deque — O(1) on both ends
from collections import deque
q = deque([1, 2, 3, 4])
q.popleft()            # O(1)
q.appendleft(0)        # O(1)
print(q)               # deque([0, 2, 3, 4])

External links

Exercise

Build a list of dicts representing five people: each with name (string) and age (int). (a) Sort the list by age ascending. (b) Sort by age descending. (c) Sort by name length. (d) Pop the oldest person off the end after sorting ascending and print just that person. Use only .sort / sorted / pop — no manual loops.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.