How to concatenate two lists in Python
Use the + operator: combined = a + b. It returns a new list and leaves a and b untouched. To grow an existing list instead, use a.extend(b).
The real choice here isn't syntax, it's who owns the result: a + b builds a new list, while extend() and += mutate a in place — which anything else holding a reference to a will see. Each example runs on this page: hit Run, then edit the code and run it again.
1The + operatorRecommended
+ on two lists returns a brand-new list holding the items of the first followed by the items of the second. Both inputs are left exactly as they were.
Output
Prints [1, 2, 3, 4, 5, 6] then [1, 2, 3] [4, 5, 6] — the originals are unchanged. Both operands must be lists: [1, 2] + (3, 4) raises TypeError: can only concatenate list (not "tuple") to list.
2extend() and += (in place)
a.extend(b) appends every item of b onto a itself and returns None. a += b is the same operation with different spelling — for lists, += calls __iadd__, so it mutates rather than rebinding. Use either when you want to grow a list you already have instead of paying for a copy.
Output
Output: [1, 2, 3, 4, 5, 6], ['x', 'y', 'z'], ['x', 'y', 'z', 'p', 'q']. Note that extend() and += accept any iterable — tuples, sets, generators, even strings (which add one character per item). Don't confuse it with append(), which would push the whole list in as a single nested element.
3Unpacking with [*a, *b]
The * unpacking operator spreads each iterable into a fresh list literal. It reads well and, unlike +, scales to any number of sources in one expression — and lets you drop extra items in wherever you like.
Output
Prints [1, 2, 3, 4], [1, 2, 3, 4, 5, 6] and [0, 1, 2, 3, 4, 99]. Chaining a + b + c would build a throwaway intermediate list for a + b; the unpacked literal allocates once.
4itertools.chain (lazy)
chain() doesn't concatenate at all — it returns an iterator that walks the inputs back to back without copying a single element. That's the one to reach for when the lists are large, or when there are many of them and you only need to iterate the result once. chain.from_iterable() takes the lists as one sequence instead of as separate arguments.
Output
Prints 1 2 3 4 5 6, then 21, then [1, 2, 3, 4, 5, 6]. Remember it's single-pass: once you've consumed the iterator it's empty, so wrap it in list(...) if you need a real list you can index or reuse.
5Which should you use?
| Method | Result | Cost | Best for |
|---|---|---|---|
| a + b | New list | One copy | Two lists, originals kept |
| a.extend(b) / a += b | In place | Fastest | Growing a list you own |
| [*a, *b] | New list | One copy | Three or more sources |
| chain(a, b) | Iterator | No copy | Huge or many lists, one pass |
6Common variation: the += aliasing gotcha
This is the bug += hides. If two names point at the same list — a second variable, a function parameter, an item inside another structure — then += changes what both of them see, while a = a + b quietly rebinds only the name on the left.
Output
After the += line both names print [1, 2, 3, 4] — the 4 landed in original too. After the + line they diverge: original is still [1, 2, 3, 4] while alias is [1, 2, 3, 4, 5], because + built a new list and only alias now refers to it. When a function receives a list and must not surprise its caller, concatenate with +.
Frequently asked questions
What is the difference between + and extend() in Python?
a + b builds and returns a new list, leaving both originals untouched. a.extend(b) mutates a in place and returns None, so it is faster and allocation-free but visible to anything else holding a reference to a.
Is a += b the same as a = a + b for lists?
Not quite. For lists += calls __iadd__, which extends the list in place, so every other name bound to that same list sees the new items. a = a + b creates a new list and rebinds only a. The printed result looks identical until something else is aliasing the list.
How do I concatenate more than two lists at once?
Use unpacking — [*a, *b, *c] — which allocates the result once instead of building an intermediate list per +. For a list of lists, list(itertools.chain.from_iterable(lists)) is the standard one-liner.
Can you concatenate a list and a tuple with +?
No — [1, 2] + (3, 4) raises TypeError: can only concatenate list (not "tuple") to list. Convert first with list(t), unpack with [*a, *t], or use a.extend(t), which accepts any iterable.