This guide focuses on practical ways to combine lists in Python: when to build a new list versus when to update an existing one, and which tool fits two lists, many lists, or nested lists. It follows the ideas in the official tutorial and library docs: sequence concatenation with +, in-place extension with list.extend and +=, and lazy merging with itertools.chain. For list fundamentals, see Python list; for append vs extend, see append vs extend in list.
The sections move from the smallest pattern (list1 + list2) through in-place updates, unpacking, iterators, flattening, and a clear comparison of trade-offs.
Tested on: Python 3.13.3; kernel 6.14.0-37-generic.
Best way to concatenate lists in Python
For two lists, the usual answer is the + operator: it builds a new list with every element from the left operand, then every element from the right, without changing either original list. The Python data model treats this as sequence concatenation for lists.
When you intend to grow an existing list instead of creating a new one, use list.extend(iterable) or list1 += list2. Both extend the target list in place; extend is explicit and reads well when the right-hand side is any iterable.
list1 = [1, 2, 3]
list2 = [4, 5, 6]
result = list1 + list2
print(result)Running the snippet prints [1, 2, 3, 4, 5, 6], and list1 is still [1, 2, 3] because + produced a separate list.
Concatenate two lists using + operator
For lists s and t, the expression s + t returns a new list. Neither operand is modified, so other references to s and t keep seeing the old contents. That matches the documented behavior of sq.__add__ for sequences.
a = [1, 2]
b = [3, 4]
c = a + b
print(c)
print(a, b)You should see [1, 2, 3, 4] for c, while a and b stay unchanged.
Concatenate multiple lists using + operator
You can chain more than two lists by repeating +. Every pairwise + allocates a new list, so many chained additions can create a lot of temporaries; for very large data or unknown iterables, itertools.chain (later in this page) is often a better fit.
list_1 = [1, 2, 3]
list_2 = [4, 5, 6]
list_3 = [7, 8, 9]
merged = list_1 + list_2 + list_3
print(merged)This prints one flat list from 1 through 9.
Combine lists using extend()
The list method extend(iterable) appends each item from the iterable to the end of the list, in order. It mutates the list in place and returns None, which is the usual pattern for mutating methods on built-in collections. For the full extend API, see Python list extend.
list_1 = [1, 2, 3]
list_2 = [4, 5, 6]
list_1.extend(list_2)
print(list_1)After extend, list_1 is [1, 2, 3, 4, 5, 6]. To build a fresh list without touching the inputs, start from an empty list and extend from each source.
list_1 = [1, 2, 3]
list_2 = [4, 5, 6]
merged = []
merged.extend(list_1)
merged.extend(list_2)
print(merged)Concatenate lists using += operator
For lists, augmented assignment list1 += list2 is equivalent in effect to extending list1 with the items from list2: the left-hand list grows in place. It is a concise spelling when you already have a variable pointing at the list you want to grow.
list_1 = [1, 2, 3]
list_2 = [4, 5, 6]
list_1 += list_2
print(list_1)As with extend, list_1 now contains all six numbers in one list.
Merge lists using unpacking
In Python 3.5+, PEP 448 allows unpacking inside a list display. [*a, *b, *c] builds a new list with all items from each iterable in order. It reads well when you have several lists and want one new list without mutating the originals.
list_1 = [1, 2, 3]
list_2 = [4, 5, 6]
list_3 = [7, 8, 9]
merged = [*list_1, *list_2, *list_3]
print(merged)This yields the same flat sequence as chained +, with a single list literal.
Concatenate many lists using itertools.chain()
itertools.chain returns an iterator that yields elements from the first iterable until it is exhausted, then continues with the next, until all are exhausted. Wrapping it in list(...) materializes a full list when you need one; otherwise you can stream values and save memory.
from itertools import chain
list_1 = [1, 2, 3]
list_2 = [4, 5, 6]
list_3 = [7, 8, 9]
merged = list(chain(list_1, list_2, list_3))
print(merged)For a single iterable of iterables (for example a list of lists), chain.from_iterable applies the same idea without writing one argument per sublist.
Flatten a list of lists
People often store [[1, 2], [3, 4], [5, 6]] and want [1, 2, 3, 4, 5, 6]. A list comprehension walks each sublist and each item; chain.from_iterable does the same job through the iterator protocol. See flatten a list in Python for one-level and deep flattening patterns.
lists = [[1, 2], [3, 4], [5, 6]]
result = [item for sublist in lists for item in sublist]
print(result)from itertools import chain
lists = [[1, 2], [3, 4], [5, 6]]
result = list(chain.from_iterable(lists))
print(result)Both approaches only flatten one level. If inner values are themselves nested lists, you need recursion, an explicit stack, or a library designed for deep flattening.
Add one list as a nested item using append()
list.append(x) adds a single object x to the end of the list. If x is another list, you get one nested list, not a merge. That is correct API behavior, but it is a frequent mix-up when you meant to concatenate.
list1 = [1, 2, 3]
list2 = [4, 5, 6]
list1.append(list2)
print(list1)You should see [1, 2, 3, [4, 5, 6]] because the whole of list2 became one element. To merge the items, use extend (or +=) on a copy if you still need the original list1 unchanged.
list1 = [1, 2, 3]
list2 = [4, 5, 6]
list1.extend(list2)
print(list1)This prints [1, 2, 3, 4, 5, 6].
+ vs extend() vs += vs unpacking vs chain()
| Approach | Creates new list? | Changes original? | Best for |
|---|---|---|---|
list1 + list2 |
Yes | No (inputs unchanged) | Simple two-list concatenation |
list1.extend(list2) |
No | Yes (list1 grows) |
Updating an existing list in place |
list1 += list2 |
No | Yes (list1 grows) |
Short in-place merge on a named list |
[*a, *b, *c] |
Yes | No | Merging several lists into one literal cleanly |
itertools.chain(...) |
Iterator first; list(...) if you need a list |
No inputs mutated by chain itself |
Many iterables, large data, or streaming |
list1.append(list2) |
No | Yes | Storing another list as a single nested element (usually not “concatenation”) |
Common mistakes when concatenating lists
- Using
appendwhen you meantextend, which nests the second list instead of merging its items. - Assuming
extendreturns a new list; it returnsNoneand mutates the receiver, soresult = list1.extend(list2)setsresulttoNonewhile still changinglist1. - Building huge results with
+inside a tight loop, which can allocate many intermediate lists; preferextendon one accumulator orchainfor large inputs. - Confusing list concatenation with
str.join:joinworks on strings and returns one string, not a merged list of arbitrary objects. - Flattening with a comprehension or
chain.from_iterablewhen the structure is deeper than one level of lists, which leaves inner lists untouched.
list1 = [1, 2, 3]
list2 = [4, 5, 6]
result = list1.extend(list2)
print(result)That prints None while list1 is now [1, 2, 3, 4, 5, 6], which matches the documented “mutating methods return None” pattern for built-in mutable collections.
Python list concatenation quick reference table
| Need | Use |
|---|---|
| Join two lists into a new list | list1 + list2 |
| Join many lists into a new list | [*a, *b, *c] or chained + |
| Modify the first list | list1.extend(list2) |
| Short in-place merge | list1 += list2 |
| Merge many iterables lazily | itertools.chain(*iterables) |
| Flatten list of lists | [x for sub in lists for x in sub] or list(chain.from_iterable(lists)) |
| Add one list as a nested item | list1.append(list2) (intentional nesting only) |
Summary
Use list1 + list2 when you want a new list and both operands should stay unchanged. Use extend or += on the list you own when you want in-place growth, remembering that extend returns None. Unpacking in [*a, *b] is a readable way to merge several lists into a new list literal. For many or large iterables, prefer itertools.chain or chain.from_iterable so you are not building large temporary lists at every step. Treat append as “add one object,” not as list concatenation, and use a comprehension or chain.from_iterable when you mean to flatten one level of nesting. For more control flow around building lists, see the Python for loop tutorial and the official list documentation.
References
- Data model:
__add__and sequence operations - More on lists (
extend,append) itertools.chainandchain.from_iterable- PEP 448 — Additional unpacking generalizations

