list.append()
Add one item to the end — in place, returning None. The most-used list method, and the most-misassigned one.
Common call
items.append(x)
Returns
None — the list itself grows
Replaces
appends ONE item; a list argument becomes a nested list
Watch out
x = lst.append(v) sets x to None — the classic bug
list.append(itemitem — The object to add. Added as ONE element — even if it is itself a list.type: Any · required)
→ None
Demo
Live evaluation
Try:
Inputs
listlistcomma-separated items
itemAnyitem to add
Output
['a', 'b', 'c'].append('d')
None
The output is None — really. That IS the lesson: append mutates the list in place (after ["a","b","c"].append("d") the list is ["a","b","c","d"]) and returns nothing. Assigning the result to a variable is the #1 append bug — see Pitfalls.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| item | Any | yes | The object to add. Added as ONE element — even if it is itself a list. |
Return value
None — None — always. The list grows in place; there is nothing useful to return.
Common patterns
Build a list in a loop
The bread-and-butter accumulation pattern.
results = [] for item in source: results.append(transform(item))
Know when a comprehension is better
Pure transform-and-collect loops read better as comprehensions.
results = [transform(x) for x in source]
Stack push
append + pop() from the end = LIFO stack, both O(1).
stack.append(job) job = stack.pop()
Examples
1. Append one item
lst = [1, 2]
lst.append(3)
lst
Returns
[1, 2, 3]2. Appending a list nests it
lst = [1, 2]
lst.append([3, 4])
lst
Returns
[1, 2, [3, 4]]3. The return value is None
result = [1].append(2)
print(result)
Returns
NonePitfalls
1. Assigning the result loses the list
append returns None by design — never assign it.
Wrong
lst = lst.append(x)
lst is None
Fix
lst.append(x) # no assignment
list grew in place
2. append vs extend
append adds its argument as ONE element; extend splices an iterable in.
Nested
lst = [1, 2] lst.append([3, 4])
[1, 2, [3, 4]]
Flat
lst = [1, 2] lst.extend([3, 4])
[1, 2, 3, 4]
3. Appending to a shared default argument
The infamous mutable-default trap: one list shared across calls.
Shared state
def add(x, items=[]): items.append(x) return items
grows across unrelated calls
Fix
def add(x, items=None): items = items if items is not None else [] items.append(x) return items
fresh list per call
When to use
Use it
- Accumulating results one at a time
- Stack push (with pop for the pop side)
- Appending in loops with logic a comprehension cannot express
Reach for something else
- Adding all items of an iterable → list.extend
- Pure transform loops → list comprehension
- Inserting elsewhere than the end → list.insert (O(n))
- Fast appends AND pops at both ends → collections.deque
Notes
Complexity
Amortized O(1) — the array over-allocates as it grows
Return
None; the list mutates
CPython impl
Objects/listobject.c :: list_append
Memory
Occasional reallocation with growth factor ~1.125
Thread-safe
append itself is atomic in CPython, but do not rely on it for logic
FAQ
Python convention: methods that mutate in place return None, so you cannot mistake them for ones returning new objects. It rules out fluent chaining on purpose.
History
2.0
Core list method, unchanged semantics since.