Question
How can I concatenate two lists in Python?
For example:
listone = [1, 2, 3]
listtwo = [4, 5, 6]
Expected result:
joinedlist = [1, 2, 3, 4, 5, 6]
Short Answer
By the end of this page, you will understand how list concatenation works in Python, the difference between creating a new combined list and modifying an existing one, and when to use +, extend(), unpacking, or other common approaches.
Concept
In Python, concatenating lists means combining the elements of two or more lists into one sequence.
If you have:
listone = [1, 2, 3]
listtwo = [4, 5, 6]
then concatenation produces:
[1, 2, 3, 4, 5, 6]
This matters because lists are one of the most common data structures in Python. Developers often need to combine:
- results from multiple API calls
- rows from separate data sources
- user inputs collected in stages
- default values with custom values
There are several ways to concatenate lists in Python, and the best choice depends on whether you want to:
- create a new list without changing the originals, or
- modify an existing list in place
The most beginner-friendly approach is:
joinedlist = listone + listtwo
This creates a new list.
Another common approach is:
listone.extend(listtwo)
This changes listone itself.
Understanding that difference is important in real programs, because changing a list in place can affect other parts of your code if they reference the same object.
Mental Model
Think of a Python list like a row of boxes.
listoneis one row of boxes:[1, 2, 3]listtwois another row of boxes:[4, 5, 6]
Concatenation means placing the second row directly after the first row.
Using + is like building a brand new row that contains boxes from both rows.
Using extend() is like taking the first row and attaching the second row onto the end of it.
So:
+=> make a new combined listextend()=> grow the existing list
Syntax and Examples
Basic syntax
1. Using +
listone = [1, 2, 3]
listtwo = [4, 5, 6]
joinedlist = listone + listtwo
print(joinedlist)
Output:
[1, 2, 3, 4, 5, 6]
This is the clearest way to concatenate two lists when you want a new list.
2. Using extend()
listone = [1, 2, 3]
listtwo = [4, 5, 6]
listone.extend(listtwo)
print(listone)
Output:
[1, 2, 3, 4, 5, 6]
This modifies listone directly.
3. Using unpacking
listone = [1, 2, 3]
listtwo = [4, 5, 6]
joinedlist = [*listone, *listtwo]
print(joinedlist)
Output:
[1, 2, 3, 4, 5, 6]
This is useful when combining several lists or mixing individual values with lists.
4. Using +=
listone = [1, 2, 3]
listtwo = [4, 5, 6]
listone += listtwo
print(listone)
Output:
[1, 2, 3, 4, 5, 6]
For lists, += usually modifies the original list, similar to extend().
Beginner-friendly example
morning_tasks = ["email", "meeting"]
afternoon_tasks = ["coding", "review"]
all_tasks = morning_tasks + afternoon_tasks
print(all_tasks)
Output:
['email', 'meeting', 'coding', 'review']
This combines two task lists into one schedule.
Step by Step Execution
Consider this example:
listone = [1, 2, 3]
listtwo = [4, 5, 6]
joinedlist = listone + listtwo
print(joinedlist)
Step by step:
- Python creates
listonewith the values1,2, and3. - Python creates
listtwowith the values4,5, and6. listone + listtwotells Python to build a new list.- Python copies the items from
listoneinto the new list. - Python then copies the items from
listtwoafter them. - The new list is assigned to
joinedlist. print(joinedlist)displays:
[1, 2, 3, 4, 5, 6]
Now compare it with extend():
listone = [1, 2, 3]
listtwo = [4, 5, 6]
listone.extend(listtwo)
print(listone)
Step by step:
- Python creates
listone. - Python creates
listtwo. listone.extend(listtwo)takes each item fromlisttwo.- It appends those items to the end of
listone. - No new combined list variable is required.
print(listone)shows the updated list.
The key difference is that + returns a new list, while extend() changes the existing one.
Real World Use Cases
List concatenation appears in many practical situations.
Combining paginated API results
page1 = ["user1", "user2"]
page2 = ["user3", "user4"]
all_users = page1 + page2
Merging file processing results
csv_rows = ["row1", "row2"]
json_rows = ["row3", "row4"]
all_rows = csv_rows + json_rows
Building a final report
errors = ["missing email"]
warnings = ["short password"]
messages = errors + warnings
Combining user-selected filters
default_filters = ["active"]
user_filters = ["admin", "verified"]
all_filters = default_filters + user_filters
Joining batches in data processing
batch1 = [101, 102, 103]
batch2 = [104, 105]
all_ids = batch1 + batch2
In each case, the idea is the same: preserve the order and place one list after another.
Real Codebase Usage
In real projects, developers choose list concatenation based on intent.
Creating a new result safely
If you do not want to change the original lists:
def build_menu(default_items, custom_items):
return default_items + custom_items
This is common in functions because it avoids side effects.
Updating an existing list in place
If you are collecting results over time:
all_logs = []
all_logs.extend(["started"])
all_logs.extend(["finished"])
This is useful when accumulating values in loops or pipelines.
Guard clauses before concatenation
Developers often validate inputs first:
def combine_lists(a, b):
if not isinstance(a, list) or not isinstance(b, list):
raise TypeError("Both arguments must be lists")
return a + b
Combining optional values
def get_tags(system_tags, user_tags=None):
user_tags = user_tags or []
return system_tags + user_tags
This pattern avoids errors when a value might be None.
Working with many lists
all_numbers = [*range(3), *range(3, 6)]
Or:
parts = [[1, 2], [3, 4], [5, 6]]
result = []
for part in parts:
result.extend(part)
In production code, readability matters. For two lists, + is often the clearest choice. For repeated accumulation, extend() is usually preferred.
Common Mistakes
1. Using append() instead of concatenation
Broken code:
listone = [1, 2, 3]
listtwo = [4, 5, 6]
listone.append(listtwo)
print(listone)
Output:
[1, 2, 3, [4, 5, 6]]
Why this happens:
append()adds the entire second list as one item- it does not merge the elements
Use this instead:
listone.extend(listtwo)
or:
joinedlist = listone + listtwo
2. Expecting extend() to return a new list
Broken code:
listone = [1, 2, 3]
listtwo = [4, 5, 6]
joinedlist = listone.extend(listtwo)
print(joinedlist)
Output:
None
Why this happens:
extend()modifies the list in place- it returns
None
Correct usage:
listone.extend(listtwo)
print(listone)
3. Accidentally changing the original list
original = [1, 2]
extra = [3, 4]
combined = original
combined.extend(extra)
print(original)
Output:
[1, 2, 3, 4]
Why this happens:
combined = originaldoes not copy the list- both names point to the same list object
Safer version:
combined = original + extra
4. Trying to concatenate a list with a non-list
Broken code:
numbers = [1, 2, 3]
result = numbers + 4
This raises an error because + expects another list.
Correct version:
result = numbers + [4]
5. Forgetting that order matters
print([1, 2] + [3, 4])
print([3, 4] + [1, 2])
These produce different results. Concatenation preserves order exactly.
Comparisons
| Approach | Creates new list? | Modifies original? | Good for | Example |
|---|---|---|---|---|
list1 + list2 | Yes | No | Clear combination of two lists | result = a + b |
list1.extend(list2) | No | Yes | Adding items into an existing list | a.extend(b) |
list1 += list2 | Usually no | Yes | Short in-place update | a += b |
[ *list1, *list2 ] | Yes | No | Combining multiple sources clearly | result = [*a, *b] |
append() | No | Yes | Adding one item, not merging lists | a.append(b) |
append() vs extend()
| Method | Result |
|---|---|
a.append(b) | Adds b as a single element |
a.extend(b) | Adds each item from b |
Example:
a = [1, 2]
b = [3, 4]
a.append(b)
print(a)
Output:
[1, 2, [3, 4]]
But:
a = [1, 2]
b = [3, 4]
a.extend(b)
print(a)
Output:
[1, 2, 3, 4]
Cheat Sheet
Quick reference
Create a new combined list
result = list1 + list2
Modify the first list in place
list1.extend(list2)
Short in-place form
list1 += list2
Use unpacking
result = [*list1, *list2]
Important rules
+returns a new listextend()changes the existing listappend()adds one item, even if that item is a list- concatenation preserves element order
- both sides of
+must be lists
Common outputs
[1, 2] + [3, 4] # [1, 2, 3, 4]
a = [1, 2]
a.extend([3, 4]) # a becomes [1, 2, 3, 4]
a = [1, 2]
a.append([3, 4]) # a becomes [1, 2, [3, 4]]
Edge cases
[] + [1, 2] # [1, 2]
[1, 2] + [] # [1, 2]
[] + [] # []
[1, 2] + [3] # valid
[1, 2] + 3 # error
FAQ
How do I join two lists in Python?
Use + if you want a new list:
result = list1 + list2
What is the difference between append() and extend() in Python?
append() adds one item to the end of a list. extend() adds each item from another iterable.
Does + modify the original list in Python?
No. + creates a new list and leaves the original lists unchanged.
Does extend() return a new list?
No. It modifies the existing list and returns None.
Can I concatenate more than two lists in Python?
Yes.
result = list1 + list2 + list3
You can also use unpacking:
result = [*list1, *list2, *list3]
Can I concatenate a list with a tuple or an integer?
Not directly with + unless both sides are lists.
[1, 2] + [3] # valid
[1, 2] + (3,) # error
Which is better: + or extend()?
Use + when you want a new list. Use extend() when you want to update an existing list in place.
Mini Project
Description
Build a small Python script that combines two shopping lists into one final list. This demonstrates how list concatenation works in a realistic situation where data comes from different sources.
Goal
Create a program that merges two lists of items and prints the final combined shopping list.
Requirements
Requirement 1 Requirement 2 Requirement 3
Keep learning
Related questions
@staticmethod vs @classmethod in Python Explained
Learn the difference between @staticmethod and @classmethod in Python with clear examples, use cases, mistakes, and a mini project.
Add Rows to a Pandas DataFrame in Python
Learn how to add rows to a Pandas DataFrame, why repeated row appends are slow, and when to use loc, concat, or record lists.
Call a Function by Name in a Python Module
Learn how to call a function by name in a Python module using strings, getattr, and safe patterns for dynamic function dispatch.