What is the difference between append and extend on a Python list?
Short answer
append adds its argument as a single element, so passing a list nests it. extend adds each item of an iterable individually. Both change the list in place and return None.
The short version
append adds whatever you give it as one single element, so appending a list produces a nested list. extend adds each item of an iterable one by one, flattening it into the existing list. Both modify the list in place and return None, which is a frequent source of bugs.
Seeing the difference
a = [1, 2]
a.append([3, 4])
print(a) # [1, 2, [3, 4]]
b = [1, 2]
b.extend([3, 4])
print(b) # [1, 2, 3, 4]
append treated [3, 4] as a single thing and tucked it in whole. extend walked through [3, 4] and added 3 and then 4.
When you want each
Use append to add one item, whatever its type, including when that item happens to be a list you want to keep whole. Use extend to concatenate the contents of another sequence onto the end.
rows = []
rows.append([1, 2]) # keep [1, 2] as one row
rows.append([3, 4])
# rows is [[1, 2], [3, 4]], a list of rows
The None trap
Because both methods change the list in place and return None, assigning the result throws the list away.
a = [1, 2]
a = a.append(3) # BUG: a is now None
The fix is to call the method for its effect and not reassign.
a = [1, 2]
a.append(3) # a is now [1, 2, 3]
extend accepts any iterable
extend does not need a list. It accepts anything you can loop over, including a string, which extends by characters and often surprises people.
c = [1, 2]
c.extend("ab")
print(c) # [1, 2, 'a', 'b']
The plus operators
For comparison, a + b creates a new list and leaves the originals alone, while a += b behaves like extend and modifies a in place. Use + when you want a fresh list and want to keep the originals untouched.