Python List append(): Add One Item to the End of a List
The append() method adds one item to the end of a Python list. It's the workhorse of the list methods, and it changes the list you call it on, so the new item is sitting right there the moment the line runs:
cart = ["milk", "eggs"]
cart.append("bread")
print(cart)
print(len(cart)) # Program output:
# ['milk', 'eggs', 'bread']
# 3 append() returns None, not the updated list. Call it on its own line so you keep the list you just changed.
Syntax and Basic Usage
items.append(x)
# adds x to the end and returns None - x (required, any type): the item to add. It goes on as one item, whatever it is.
- Returns:
None. The list itself is what changes. - Raises:
TypeErrorwhen you pass no argument or more than one.
A list doesn't care what type you hand it, so you can mix strings, numbers and even None in the same list:
todo = []
todo.append("write tests")
todo.append(42)
todo.append(None)
print(todo) # Program output:
# ['write tests', 42, None] Starting from an empty list and appending as you go is the most common way to build a list in Python, so get comfortable with it early. It works like the deli line at a Wawa on a Saturday morning: every new order joins the end, and nobody already waiting gets bumped.
What Happens When You Append a List in Python?
Python append() adds a list as one nested item. It does not unpack the list's contents. When you want the elements added one by one, that's the job extend() was built for:
first = [1, 2]
second = [1, 2]
first.append([3, 4])
second.extend([3, 4])
print(first, len(first))
print(second, len(second)) # Program output:
# [1, 2, [3, 4]] 3
# [1, 2, 3, 4] 4 The two lengths in that output tell the story. The first list grew by one, because the nested [3, 4] counts as a single item, while the second grew by two. Strings trip people the other way, because extend() loops over whatever you give it, and looping over a string gives you its characters:
letters = ["a", "b"]
letters.append("cd")
print(letters)
letters.extend("ef")
print(letters) # Program output:
# ['a', 'b', 'cd']
# ['a', 'b', 'cd', 'e', 'f'] So when you're adding a single string, use append(), because extend() would split it into characters. When you've got a list of new items, extend() is the one you want, because it adds each of them separately.
If the loops below are new to you, start with the Python learning guide.
Practical Examples
Keeping the Items That Pass a Test
The classic pattern is an empty list before a loop and an append() inside an if. Here it keeps only the scores that fall between 0 and 100:
scores = [88, -1, 72, 105, 64]
valid = []
for score in scores:
if 0 <= score <= 100:
valid.append(score)
print(valid) # Program output:
# [88, 72, 64] A list comprehension can do this filter in one line. For a single test, I'd choose that shorter form. The comprehensions guide explains the syntax.
Once the body needs a second step, like logging the rejects, I'd go with the loop, because each step gets its own line and reads top to bottom. The trade-off is a few extra lines, and on a filter this small either one does the job.
Collecting Error Messages
You can also append messages as you check a form. Collecting every problem into a list, instead of stopping at the first one, lets you show a user everything they need to fix in one go:
signup = {
"name": "",
"email": "bo@",
"age": 15,
}
errors = []
if not signup["name"]:
errors.append("name is required")
if "." not in signup["email"]:
errors.append("email looks wrong")
if signup["age"] < 16:
errors.append("must be 16 or over")
for error in errors:
print("-", error) # Program output:
# - name is required
# - email looks wrong
# - must be 16 or over Heads up: that email check is a toy, simplified on purpose to show how the messages pile up, so use a proper validator before you trust it with live signups. When the checks all pass, errors stays empty. An empty list counts as false in an if test, so if errors: tells you whether anything went wrong.
Common Pitfalls and Debugging
AttributeError: 'NoneType' object has no attribute 'append'
This is the big one. It comes from assigning the result of append() back to your variable. The method returns None, so the assignment swaps your list for None, and the next append() fails:
items = ["a", "b"]
items = items.append("c")
print(items)
items.append("d") # Program output:
# None
# Traceback (most recent call last):
# ...
# AttributeError: 'NoneType' object has no attribute 'append' The traceback points at the second append(), and that's the trap, because the bug lives on the assignment line two lines earlier. Drop the assignment and call the method on its own line:
items = ["a", "b"]
items.append("c")
print(items) # Program output:
# ['a', 'b', 'c'] Chaining two calls, as in items.append("c").append("d"), hits the same error in one line, because the second call runs on the None the first one returned. The same message also turns up when a function you wrote forgets its return, so it hands back None, and you call append() on the result.
TypeError When You Pass Two Items
Pass two values and Python refuses, because append() adds one item per call. CPython words the error in its traceback like this:
items = []
items.append("a", "b") # Program output:
# Traceback (most recent call last):
# ...
# TypeError: list.append() takes exactly one argument (2 given) To add both, pass them to extend() inside a list:
items = []
items.extend(["a", "b"])
print(items) # Program output:
# ['a', 'b'] Appending the Same List Over and Over
A list stores a reference to whatever you append, and it doesn't make a copy. So if you create one inner list outside a loop and append it three times, you've got three slots pointing at one list:
grid = []
row = []
for _ in range(3):
grid.append(row)
grid[0].append("x")
print(grid) # Program output:
# [['x'], ['x'], ['x']] You changed row 0 and all three rows changed. Build a fresh inner list on each pass instead, and each slot gets its own:
grid = []
for _ in range(3):
grid.append([])
grid[0].append("x")
print(grid) # Program output:
# [['x'], [], []] We go deeper on copying and shared references in the Python Lists guide.
Strings and Tuples Have No append()
Strings and tuples can't be changed after you create them, so neither type has an append() method. Calling it raises an AttributeError that names the type:
name = "Ada"
name.append("!") # Program output:
# Traceback (most recent call last):
# ...
# AttributeError: 'str' object has no attribute 'append' For a string, build a new one with name = name + "!". For a tuple, you get 'tuple' object has no attribute 'append', and the fix is either a new tuple or a switch to a list if the collection is meant to grow.
append() vs extend() vs +=
Three tools add to the end of a list, and the only thing you have to keep straight is how many items each one adds.
| Tool | Adds | Passing [3, 4] |
|---|---|---|
append(x) | One item | One nested list |
extend(xs) | Each item of xs | Two items, 3 and 4 |
items += xs | Each item of xs | Two items, 3 and 4 |
On a list, += behaves like extend() and changes the same list in place, including the split-a-string surprise:
nums = [1, 2]
nums += [3, 4]
print(nums)
nums += "ab"
print(nums) # Program output:
# [1, 2, 3, 4]
# [1, 2, 3, 4, 'a', 'b'] Choosing between the three comes down to how many items you've got:
- For one item, use
append(), since it's the only one of the three that never splits your item into pieces. - For several items,
extend()and+=do the same job on a list. I'd pickextend()when other code holds a reference to the same list, because the method name tells the next reader the list is changing in place. - The trade-off is length:
+=is shorter, and in a loop where nobody else touches the list, it's a perfectly good choice.
To put an item somewhere other than the end, insert() takes a position as well as the value, and the Append, Extend, and Insert section of the Lists guide shows all three side by side.
Build a List One Item at a Time
Use append() when you have one item to add to the end, and call it on its own line, because it returns None. When you have several items, pass them to extend() so each one lands as its own element. Then go build something small with it tonight, like a to-do list that grows one append() at a time.
Frequently Asked Questions
Does Python append() return a new list?
Python list.append() changes the existing list and returns None, not a new list. That is why items = items.append(x) replaces your list with None. Call items.append(x) on its own line and keep using items.
Can Python append() add several items in one call?
Python list.append() adds one item per call and accepts exactly one argument. Use extend() or += to add several items separately. Passing a list to append() adds that whole list as one nested item.
Is Python append() slow on a long list?
Python list.append() stays fast on average as a list grows. CPython keeps spare space for new items, so most calls fill a free slot. An occasional call must resize the list, which takes more work.
How do you add an item to the front of a Python list?
To add one item to the front of a Python list, use items.insert(0, x). This puts x at index 0 and shifts the existing items along. For frequent additions to the front of a long collection, use collections.deque and appendleft().
Does Python append() copy the object you pass in?
Python list.append() stores a reference to the object you pass; it does not copy the object. If you append a list and later change it, the change appears inside the outer list too. Append row.copy() when you need a separate shallow copy.
How do you append to a Python dictionary?
A Python dictionary has no append() method. Add a key-value pair with an assignment such as prices["tea"] = 3, or use update() for several pairs. If a dictionary value is a list, you can call append() on that list.
Next Steps
- Python List remove() vs pop() - taking items back out, by value or by position.
- Python Dictionaries - adding keys and values when a list is the wrong shape.
Sources
-
[1]
Data Structures: More on Lists(docs.python.org)
-
[2]
Mutable Sequence Types(docs.python.org)
-
[3]
Design and History FAQ: How are lists implemented in CPython?(docs.python.org)
Read Next
The insert() method puts one item into a list before a given index. Syntax, how negative and out-of-range indexes behave, the TypeErrors it raises, and when append(), slice assignment or deque fit better.
A Python list keeps items in the order you put them and lets you change that order later. How to create one, index and slice it, add and remove items, copy it safely, and recognize the jobs a list is wrong for.
The remove() method deletes the first matching value and pop() deletes by position and returns the item. Syntax, return values, the ValueError and IndexError each raises, and how both compare with del and clear().