Append Python: How to Add Items to a List (append vs extend vs insert vs +)

Most developers search for “append python” when they really have a bigger question: what is the *right* way to add something to a list? append() is the answer roughly 80% of the time, but Python gives you a whole family of tools, extend(), insert(), the + operator, +=, and slice assignment, and each one behaves differently. Pick the wrong one and you get a nested list where you wanted a flat one, or a silent performance problem, or a None where you expected data.

This guide treats the choice as the real topic. We will anchor on append(), because it is the workhorse, then place every other method beside it so you know exactly when to reach for which. Every claim comes with runnable code and output comments you can paste straight into an interpreter and verify.

Key Takeaways
append(x) adds ONE item to the end of a list, in place and returns None, not the list.
extend(iterable) adds EACH element of an iterable. [1,2].append([3,4]) gives [1,2,[3,4]]; extend gives [1,2,3,4].
insert(i, x) adds at a position and is O(n); append is the special case insert(len(list), x) and is O(1).
+ builds a new list; += mutates in place and behaves like extend, not append.
To add multiple items use extend or +=; to add one item, even a list as one element, use append.

The single mistake that drives most “append python” confusion is treating append and extend as interchangeable. They are not, and the difference is not stylistic, it is structural. append adds whatever you pass as one single element, even if that thing is itself a list of a thousand items. extend walks the argument and adds each element individually. So append cares about the *object*; extend cares about the object’s *contents*. Here is the consequence almost nobody internalizes until it bites them: list.append(other_list) always *nests*, producing a list-inside-a-list, while list.extend(other_list) always *flattens by one level*. Once you frame the decision as “do I want this thing as one box, or do I want what is inside the box,” choosing between every method on this page becomes mechanical.

What does append() actually do in Python?

list.append(x) adds x as a single new element at the end of a list and modifies the list in place, returning None. Per the official Python tutorial on data structures, it is equivalent to a[len(a):] = [x]. The list object itself is mutated, no copy is made, and the operation is amortized O(1).

fruits = ["apple", "banana"]
fruits.append("cherry")
print(fruits)
# Output: ['apple', 'banana', 'cherry']

The list grew by exactly one element, and it is the *same* object in memory. Because append mutates in place, anything else pointing at that list sees the change too:

a = [1, 2]
b = a            # b and a reference the SAME list
a.append(3)
print(b)
# Output: [1, 2, 3]

The one rule that prevents the most common bug: append returns None. Never write mylist = mylist.append(x), because mylist then becomes None and the next .append() raises AttributeError: 'NoneType' object has no attribute 'append'. Call it on its own line, then use the list.

What is the difference between append and extend?

This is the comparison developers search for most, and the answer is exact: append adds its argument as one element, while extend iterates the argument and adds each element. The two produce different list lengths and different shapes from the same input, so they are never truly interchangeable.

# append: one item added (the list is nested)
a = [1, 2]
a.append([3, 4])
print(a)
# Output: [1, 2, [3, 4]]    <-- length 3

# extend: each item added (the list is flattened by one level)
b = [1, 2]
b.extend([3, 4])
print(b)
# Output: [1, 2, 3, 4]      <-- length 4

extend accepts any iterable, not just lists, so strings, tuples, sets, and generators all work. That trips people up with strings, because a string is iterable character by character:

c = [1, 2]
c.extend("ab")        # a string is iterable -> each char added
print(c)
# Output: [1, 2, 'a', 'b']

d = [1, 2]
d.append("ab")        # appended as one string
print(d)
# Output: [1, 2, 'ab']

A clean mental model: mylist.extend(other) behaves like mylist += other, while mylist.append(other) is always a single insertion of one object.

How do you insert into a list at a specific position?

When position matters, insert(i, x) adds x at index i and shifts every existing element from that index rightward. The key trade-off is cost: insert is O(n) because of the shifting, whereas append is amortized O(1). That means append(x) is just the optimized special case of insert(len(list), x).

queue = ["a", "b", "c"]
queue.insert(1, "X")     # insert at index 1
print(queue)
# Output: ['a', 'X', 'b', 'c']

queue.insert(0, "first") # insert at the front
print(queue)
# Output: ['first', 'a', 'X', 'b', 'c']

Inserting at the front of a long list repeatedly is a classic performance trap, because every insertion shifts the entire list. If your workload is front-heavy, do not fight insert(0, x). Reach for collections.deque, which offers an O(1) appendleft():

from collections import deque
dq = deque([1, 2, 3])
dq.appendleft(0)
print(dq)
# Output: deque([0, 1, 2, 3])

Use insert only when you genuinely need a middle position and the list is short enough that the O(n) shift does not matter.

append vs extend vs insert vs + : the comparison table

Here is the whole family side by side, using the same [1, 2] base and a [3, 4] addition so the structural differences are obvious. Note that + is the only one that returns a brand-new list instead of mutating in place.

Method / operator What it does Mutates in place? Returns [1, 2] with [3, 4]
append(x) Adds x as ONE element at the end Yes None [1, 2, [3, 4]]
extend(it) Adds EACH element of iterable it Yes None [1, 2, 3, 4]
insert(i, x) Adds x at index i, shifts the rest Yes None [1, [3, 4], 2] at i=1
+ Concatenates, builds a NEW list No new list [1, 2, 3, 4]
+= In-place concatenate (like extend) Yes the list [1, 2, 3, 4]
Property append extend insert + +=
Items added exactly 1 one per element exactly 1 one per element one per element
Position end end any index end (new list) end
Time complexity O(1) amortized O(k) O(n) O(n+m) O(k)
Creates a copy? no no no yes no

The split that matters: append and insert add a *single object*; extend, +, and += add the *contents* of an iterable.

How do you append multiple items or a dictionary to a list?

To add multiple items at once, use extend() or +=, never append(), because append would nest the whole collection as one element. Per the Python data structures tutorial, extend is purpose-built to append all items from an iterable. To append a dictionary as a single record, append() is exactly right, because you want the whole dict as one element.

# Add MULTIPLE items -> extend or +=
nums = [1, 2]
nums.extend([3, 4, 5])
print(nums)
# Output: [1, 2, 3, 4, 5]

nums += [6, 7]            # same effect as extend
print(nums)
# Output: [1, 2, 3, 4, 5, 6, 7]

Appending a dictionary is the canonical way to build a list of records, one row per dict:

users = []
users.append({"name": "ravi", "role": "admin"})
users.append({"name": "asha", "role": "editor"})
print(users)
# Output: [{'name': 'ravi', 'role': 'admin'}, {'name': 'asha', 'role': 'editor'}]

Here the dict is, correctly, one element. If you mistakenly called users.extend({"name": "ravi"}), you would not get the dict, you would get its *keys*, because iterating a dict yields its keys. That is a subtle, real bug:

broken = []
broken.extend({"name": "ravi", "role": "admin"})
print(broken)
# Output: ['name', 'role']    <-- keys only, almost never what you wanted

When the thing you are adding is meant to stay whole, a dict, a tuple, a nested list, use append. When you want its contents spread out, use extend.

When should you use append vs the + operator?

Use append/extend/+= when you want to mutate an existing list, and use + only when you genuinely want a new list and need the original left untouched. The difference is not cosmetic: + allocates a fresh list and copies both operands, so building a list by repeated + inside a loop is O(n^2), while repeated append is O(n).

# + builds a NEW list; original is unchanged
a = [1, 2]
b = a + [3, 4]
print(a)   # Output: [1, 2]        (untouched)
print(b)   # Output: [1, 2, 3, 4]  (new list)

# += mutates in place (and is sneakily different from +)
c = [1, 2]
d = c
c += [3, 4]      # mutates the list both names point to
print(d)   # Output: [1, 2, 3, 4]  <-- d changed too!

That last block is a genuine gotcha. c = c + [3, 4] would rebind c to a new list and leave d alone, but c += [3, 4] calls list.__iadd__, which mutates in place, so d changes with it. The operators look almost identical and behave differently.

For accumulating values in a loop, append is the correct, performant tool. Never rebuild with + each iteration:

# RIGHT: O(n) overall
squares = []
for n in range(1, 6):
    squares.append(n * n)
print(squares)
# Output: [1, 4, 9, 16, 25]

# WRONG: O(n^2), copies the whole list every iteration
squares = []
for n in range(1, 6):
    squares = squares + [n * n]   # avoid this pattern

If you find yourself looping just to transform one iterable into another, a list comprehension is usually cleaner and slightly faster than loop-plus-append. Reach for the explicit loop when the logic has multiple branches, side effects, or populates several lists at once. Comfort with looping constructs like and makes these patterns second nature.

How DarazHost gives your Python code a real home

Snippets and one-off scripts run fine on a laptop, but list-processing pipelines, schedulers, and data jobs deserve infrastructure you control. DarazHost VPS and dedicated servers give developers a real, controllable Python environment, install any Python version, run scripts and long-lived services on guaranteed resources, and manage everything with full root access, backed by 24/7 support. When your loops and data-mutation code graduate from prototype to production, this is where they belong. For the complete picture on standing up an environment that is genuinely yours, read our pillar guide: Hosting for Developers: The Complete Guide to a Real Environment You Control.

Once your code is mutating lists across modules and services, the deeper language fundamentals are worth keeping sharp, see and for the building blocks underneath all of this.

Frequently asked questions

What is the main difference between append and extend in Python? append(x) adds its argument as one single element, so a list argument gets nested. extend(iterable) iterates the argument and adds each element individually, flattening by one level. Use append to add one object whole, and extend to add many items at once.

Does append() modify the original list or return a new one? It modifies the original list in place and returns None, never a new list. If you need a separate copy, make one first with new = old[:] or old.copy(), then append to the copy. Only the + operator returns a brand-new list.

How do I append multiple items to a list at once? Use extend() with an iterable, mylist.extend([4, 5, 6]), or the += operator, mylist += [4, 5, 6]. Both add each element individually. Using append([4, 5, 6]) would add the whole list as a single nested element, which is usually not what you want.

How do I add a dictionary to a list in Python? Use append(), because you want the entire dictionary kept as one element: records.append({"id": 1}). Do not use extend() with a dict, since iterating a dictionary yields only its keys, so you would end up with a list of key strings instead of the dictionary itself.

Why is repeatedly using + slower than append in a loop? + builds a brand-new list and copies both operands every time, so growing a list with + inside a loop is O(n^2). append mutates the existing list in amortized O(1), making the whole loop O(n). Always accumulate with append or extend, not repeated +.

About the Author

Leave a Reply