How do I concatenate two lists in Python?
Example:
listone = [1, 2, 3]
listtwo = [4, 5, 6]
Expected outcome:
>>> joinedlist
[1, 2, 3, 4, 5, 6]
In Python, you can concatenate two lists using several methods including the + operator, the extend() method, or the * operator with unpacking. The most straightforward approach is using the + operator, which creates a new list containing all elements from both original lists. For in-place concatenation, you can use the extend() method, and for more advanced scenarios, you might consider list comprehensions or the itertools.chain() function.
Contents
- Using the + Operator
- Using the extend() Method
- Using the * Operator with Unpacking
- Using List Comprehensions
- Using itertools.chain()
- Performance Comparison
- Best Practices
Using the + Operator
The simplest and most readable way to concatenate two lists in Python is using the + operator. This method creates a new list containing all elements from both lists in order.
listone = [1, 2, 3]
listtwo = [4, 5, 6]
# Using the + operator
joinedlist = listone + listtwo
print(joinedlist) # Output: [1, 2, 3, 4, 5, 6]
This approach is straightforward and creates a new list without modifying the original lists. It’s the most commonly used method for list concatenation in Python due to its clarity and simplicity.
Advantages:
- Easy to read and understand
- Doesn’t modify original lists
- Works with multiple lists:
list1 + list2 + list3
Disadvantages:
- Creates a new list in memory
- Can be inefficient for very large lists
Using the extend() Method
The extend() method modifies a list by adding all elements from another list to the end of the original list. This is useful when you want to concatenate lists in-place.
listone = [1, 2, 3]
listtwo = [4, 5, 6]
# Using extend() method
listone.extend(listtwo)
print(listone) # Output: [1, 2, 3, 4, 5, 6]
If you want to keep the original lists unchanged, you first create a copy and then extend it:
listone = [1, 2, 3]
listtwo = [4, 5, 6]
# Create a copy and extend
joinedlist = list1.copy()
joinedlist.extend(list2)
print(joinedlist) # Output: [1, 2, 3, 4, 5, 6]
Advantages:
- Efficient for in-place concatenation
- Memory efficient when modifying existing lists
- Can be chained with other list operations
Disadvantages:
- Modifies the original list (unless you create a copy first)
- Less readable for simple concatenation
Using the * Operator with Unpacking
Python’s unpacking operator * can be used to concatenate multiple lists in a single expression:
listone = [1, 2, 3]
listtwo = [4, 5, 6]
# Using * operator with unpacking
joinedlist = [*listone, *listtwo]
print(joinedlist) # Output: [1, 2, 3, 4, 5, 6]
This method is particularly useful when you have multiple lists to concatenate:
list1 = [1, 2]
list2 = [3, 4]
list3 = [5, 6]
# Concatenating multiple lists
result = [*list1, *list2, *list3]
print(result) # Output: [1, 2, 3, 4, 5, 6]
You can also insert elements between lists:
list1 = [1, 2]
list2 = [3, 4]
# Inserting a separator
result = [*list1, 99, *list2]
print(result) # Output: [1, 2, 99, 3, 4]
Advantages:
- Clean and modern syntax
- Flexible - allows inserting elements between lists
- Works with multiple lists easily
- Creates a new list without modifying originals
Disadvantages:
- Slightly more verbose than simple
+operator- Requires Python 3.5+ for this syntax
Using List Comprehensions
While not strictly concatenation, you can use list comprehensions to combine elements from multiple lists:
list1 = [1, 2, 3]
list2 = [4, 5, 6]
# Using list comprehension
joinedlist = [x for lst in [list1, list2] for x in lst]
print(joinedlist) # Output: [1, 2, 3, 4, 5, 6]
This approach is more complex than other methods but can be useful in specific scenarios, especially when you need to filter or transform elements during concatenation.
# With filtering and transformation
list1 = [1, 2, 3]
list2 = [4, 5, 6, 7]
# Only include even numbers and multiply by 2
result = [x * 2 for lst in [list1, list2] for x in lst if x % 2 == 0]
print(result) # Output: [4, 8, 12]
Advantages:
- Allows filtering and transformation during concatenation
- Flexible and powerful
- Can handle complex logic
Disadvantages:
- More complex syntax
- Can be less readable for simple concatenation
- Generally slower than direct concatenation methods
Using itertools.chain()
For very large lists, itertools.chain() can be more memory-efficient as it returns an iterator rather than creating a new list:
import itertools
list1 = [1, 2, 3]
list2 = [4, 5, 6]
# Using itertools.chain
joined_iterator = itertools.chain(list1, list2)
joinedlist = list(joined_iterator)
print(joinedlist) # Output: [1, 2, 3, 4, 5, 6]
If you don’t need a list and can work with an iterator, this approach is even more memory-efficient:
import itertools
list1 = [1, 2, 3]
list2 = [4, 5, 6]
# Working with the iterator directly
for item in itertools.chain(list1, list2):
print(item, end=' ') # Output: 1 2 3 4 5 6
Advantages:
- Memory efficient for large lists
- Returns an iterator that can be processed lazily
- Can chain multiple iterables
Disadvantages:
- Requires importing itertools
- Need to convert to list for most use cases
- Slightly more complex syntax
Performance Comparison
Different concatenation methods have different performance characteristics. Here’s a comparison of the main approaches:
| Method | Time Complexity | Space Complexity | Modifies Original | Best Use Case |
|---|---|---|---|---|
list1 + list2 |
O(n+m) | O(n+m) | No | Simple, readable concatenation |
list1.extend(list2) |
O(m) | O(1) | Yes | In-place concatenation |
[*list1, *list2] |
O(n+m) | O(n+m) | No | Modern syntax with flexibility |
itertools.chain() |
O(1) for iterator | O(1) for iterator | No | Memory-efficient processing |
| List comprehension | O(n+m) | O(n+m) | No | Complex transformations |
For small to medium-sized lists, the performance differences are negligible. For very large lists, extend() is most memory-efficient for in-place operations, while itertools.chain() is best for memory-efficient iteration.
import timeit
# Performance test setup
list1 = list(range(1000))
list2 = list(range(1000, 2000))
# Testing different methods
plus_time = timeit.timeit('list1 + list2', setup='from __main__ import list1, list2', number=10000)
extend_time = timeit.timeit('list1.copy(); temp.extend(list2)', setup='from __main__ import list1, list2; temp = list1.copy()', number=10000)
unpack_time = timeit.timeit('[*list1, *list2]', setup='from __main__ import list1, list2', number=10000)
print(f"+ operator: {plus_time:.4f} seconds")
print(f"extend(): {extend_time:.4f} seconds")
print(f"unpacking: {unpack_time:.4f} seconds")
Best Practices
When choosing a list concatenation method in Python, consider these guidelines:
When to Use Each Method
Use + operator when:
- You want simple, readable code
- You need to concatenate just two lists
- You want to keep original lists unchanged
- You’re working with small to medium-sized lists
Use extend() when:
- You want to modify a list in-place
- You’re concerned about memory efficiency
- You’re building a list in a loop
Use unpacking (*) when:
- You want modern, flexible syntax
- You need to concatenate multiple lists
- You want to insert elements between lists
- You’re using Python 3.5+
Use itertools.chain() when:
- You’re working with very large lists
- You need memory-efficient iteration
- You’re processing lists sequentially without storing the result
Common Pitfalls to Avoid
-
Modifying Original Lists: Remember that
extend()modifies the list in-place. If you need to preserve the original, create a copy first. -
Inefficient Concatenation in Loops: Avoid repeated concatenation in loops using
+operator, as it creates new lists each time. Useextend()or list comprehensions instead.
# Inefficient - creates many intermediate lists
result = []
for sublist in list_of_lists:
result = result + sublist # Bad!
# Efficient - extends the list in-place
result = []
for sublist in list_of_lists:
result.extend(sublist) # Good!
- Memory Issues with Large Lists: For very large lists, consider
itertools.chain()or generator expressions to avoid memory problems.
Advanced Techniques
For more complex scenarios, you can combine these methods:
# Conditional concatenation with unpacking
list1 = [1, 2, 3]
list2 = [4, 5, 6]
list3 = [7, 8, 9]
# Only include list2 if condition is met
condition = True
result = [*list1, *list2] if condition else [*list1, *list3]
# Concatenate multiple lists with separator
lists = [[1, 2], [3, 4], [5, 6]]
separator = [0]
result = []
for i, lst in enumerate(lists):
result.extend(lst)
if i < len(lists) - 1:
result.extend(separator)
Conclusion
Python offers several effective methods for concatenating lists, each with its own advantages and use cases:
+operator is the most straightforward and readable method for simple concatenationextend()method is efficient for in-place concatenation and memory optimization- Unpacking operator (
*) provides modern, flexible syntax for multiple lists itertools.chain()offers memory-efficient iteration for large datasets- List comprehensions allow complex transformations during concatenation
Choose the method that best fits your specific needs: readability, performance, memory efficiency, or flexibility. For most everyday programming, the + operator or extend() method will serve you well, while the unpacking syntax provides a modern alternative for more complex scenarios.