By Safa Mulani and Vinayak Baranwal
In this tutorial, we will unveil different python list concatenation methods to concatenate or combine together multiple lists in Python. Python Lists serve the purpose of storing homogeneous elements and perform manipulations on the same.
In general, Concatenation is the process of joining the elements of a particular data-structure in an end-to-end manner.
If you want to learn about adding elements individually, check Python Add to List, or for working with strings see Concatenate String and Int in Python.
+
operator and list comprehension create new lists, preserving originals.extend()
and the naive for-loop modify lists in-place, which is memory efficient.*
operator provides a concise syntax for concatenation.itertools.chain()
is useful for efficient iteration over multiple lists without creating a new list.sum()
and reduce()
exist but are less common and often less efficient.This tutorial covers the following methods for concatenating lists in Python:
Best for: Small-to-medium lists when you need a new list and want simple, readable code.
The '+' operator
can be used to concatenate two lists. It appends one list at the end of the other list and results in a new list as output. This is a common way to combine lists in Python.
Example:
list1 = [10, 11, 12, 13, 14]
list2 = [20, 30, 42]
res = list1 + list2
print ("Concatenated list:\n" + str(res))
Output:
Concatenated list:
[10, 11, 12, 13, 14, 20, 30, 42]
Best for: Teaching/basic control flow or when you must append with extra per-item logic.
In the Naive method, a for loop is used to traverse the second list. After this, the elements from the second list get appended to the first list. The first list results out to be the concatenation of the first and the second list.
Example:
list1 = [10, 11, 12, 13, 14]
list2 = [20, 30, 42]
print("List1 before Concatenation:\n" + str(list1))
for x in list2 :
list1.append(x)
print ("Concatenated list i.e. list1 after concatenation:\n" + str(list1))
Output:
List1 before Concatenation:
[10, 11, 12, 13, 14]
Concatenated list i.e. list1 after concatenation:
[10, 11, 12, 13, 14, 20, 30, 42]
Best for: Creating a new list with filtering or transformation while concatenating.
Python List Comprehension is an alternative method to concatenate two lists in Python. List Comprehension is basically the process of building/generating a list of elements based on an existing list. This is a useful python concatenate list of lists technique.
It uses for loop to process and traverses the list in an element-wise fashion. The below inline for-loop is equivalent to a nested for loop.
Example:
list1 = [10, 11, 12, 13, 14]
list2 = [20, 30, 42]
res = [j for i in [list1, list2] for j in i]
print ("Concatenated list:\n"+ str(res))
Output:
Concatenated list:
[10, 11, 12, 13, 14, 20, 30, 42]
Best for: In-place updates to an existing list with minimal memory overhead.
Python’s extend() method can be used to concatenate two lists in Python. The extend()
function does iterate over the passed parameter and adds the item to the list thus, extending the list in a linear fashion.
Syntax:
list.extend(iterable)
Example:
list1 = [10, 11, 12, 13, 14]
list2 = [20, 30, 42]
print("list1 before concatenation:\n" + str(list1))
list1.extend(list2)
print ("Concatenated list i.e list1 after concatenation:\n"+ str(list1))
All the elements of the list2 get appended to list1 and thus the list1 gets updated and results as output.
Output:
list1 before concatenation:
[10, 11, 12, 13, 14]
Concatenated list i.e list1 after concatenation:
[10, 11, 12, 13, 14, 20, 30, 42]
Best for: Combining multiple lists in one expression with maximal readability.
Python’s '*' operator
can be used to easily concatenate two lists in Python.
The ‘*’ operator in Python basically unpacks the collection of items at the index arguments.
For example: Consider a list my_list = [1, 2, 3, 4].
The statement *my_list would replace the list with its elements at the index positions. Thus, it unpacks the items of the lists.
Example:
list1 = [10, 11, 12, 13, 14]
list2 = [20, 30, 42]
res = [*list1, *list2]
print ("Concatenated list:\n " + str(res))
In the above snippet of code, the statement res = [*list1, *list2] replaces the list1 and list2 with the items in the given order i.e. elements of list1 after elements of list2. This performs concatenation and results in the below output.
Output:
Concatenated list:
[10, 11, 12, 13, 14, 20, 30, 42]
Best for: Iterating over many (or large) iterables lazily; convert to list only if needed.
Python itertools modules’ itertools.chain() function can also be used to concatenate lists in Python. This is another effective python concatenate list of lists approach.
The itertools.chain()
function accepts different iterables such as lists, string, tuples, etc as parameters and gives a sequence of them as output.
It results out to be a linear sequence. The data type of the elements doesn’t affect the functioning of the chain() method.
For example: The statement itertools.chain([1, 2], [‘John’, ‘Bunny’]) would produce the following output: 1 2 John Bunny
Example:
import itertools
list1 = [10, 11, 12, 13, 14]
list2 = [20, 30, 42]
res = list(itertools.chain(list1, list2))
print ("Concatenated list:\n " + str(res))
Output:
Concatenated list:
[10, 11, 12, 13, 14, 20, 30, 42]
Best for: Very small lists only; avoid on large inputs due to quadratic behavior.
One less common method is using the built-in sum()
function to concatenate lists. This trick works by summing the lists starting with an empty list as the initial value:
Example:
list1 = [10, 11, 12]
list2 = [20, 30, 42]
res = sum([list1, list2], [])
print("Concatenated list using sum():\n", res)
Output:
Concatenated list using sum():
[10, 11, 12, 20, 30, 42]
However, note that using sum()
for list concatenation is inefficient for large lists because it repeatedly creates new lists during the addition process, leading to quadratic time complexity. It is generally better suited for small lists or educational purposes.
Best for: Functional style when combining many lists; trade readability for explicitness.
Another lesser-used approach is using operator.add
combined with functools.reduce
to concatenate multiple lists:
import operator
from functools import reduce
list1 = [10, 11]
list2 = [20, 30]
list3 = [40, 50]
res = reduce(operator.add, [list1, list2, list3])
print("Concatenated list using operator.add and reduce:\n", res)
This method is more explicit but less common in everyday Python code.
Beyond the common methods, Python also offers advanced or less conventional techniques like using sum()
and operator.add
with functools.reduce
, which may be useful in specific contexts.
When concatenating lists in Python, it’s important to understand the difference between methods that modify lists in-place versus those that create new lists.
In-place methods like extend()
and the naive for
loop append elements directly to the existing list. This is memory efficient and faster when you want to update an existing list without creating a new one.
New list creation methods such as the +
operator, list comprehension, unpacking (*
), itertools.chain()
, sum()
, and reduce()
create a new list containing all elements. While sometimes more readable and functional, these methods require additional memory and can be slower for very large lists.
Choosing the right method depends on your use case — if you want to preserve the original lists, prefer new list creation methods; if you want to update an existing list efficiently, use in-place methods.
The following quick-and-dirty timeit
snippet (run locally) demonstrates typical performance differences for large lists. Results will vary by machine and Python version, but the pattern is consistent:
import timeit
setup = """
list1 = list(range(200_000))
list2 = list(range(200_000, 400_000))
"""
print("+: ", timeit.timeit("list1 + list2", setup=setup, number=50))
print("extend():", timeit.timeit("l1=list1.copy(); l1.extend(list2)", setup=setup, number=50))
print("* unpack:", timeit.timeit("[*list1, *list2]", setup=setup, number=50))
print("chain(): ", timeit.timeit("list(__import__('itertools').chain(list1, list2))", setup=setup, number=50))
Rule of thumb: extend()
tends to be fastest for in-place updates; +
and *
are competitive for producing new lists; chain()
shines when you only need to iterate without materializing a new list.
Each method of concatenating lists comes with trade-offs. The following are general advantages and disadvantages:
+
, *
), memory efficiency (extend()
), lazy evaluation (itertools.chain()
), flexibility (list comprehensions).extend()
), new list methods consume memory (+
, *
), unconventional methods (sum()
, reduce()
) can be inefficient or less readable.Method | Time Complexity | In-place vs New List | Pros | Cons |
---|---|---|---|---|
+ operator |
O(n + m) | New List | Simple, readable | Creates new list, uses more memory |
Naive method (for loop) | O(n + m) | In-place | Explicit, no extra memory | Verbose, slower for large lists |
List Comprehension | O(n + m) | New List | Concise, flexible | Creates new list |
extend() method |
O(m) | In-place | Efficient, modifies existing list | Modifies original list |
* operator unpacking |
O(n + m) | New List | Very concise, readable | Creates new list |
itertools.chain() |
O(n + m) | New List (lazy) | Efficient for large iterables | Needs conversion to list for output |
Bonus Method 7: sum() | O(n*m) (quadratic) | New List | Simple for small lists | Inefficient for large lists |
Bonus Method 8: reduce() with operator.add | O(n + m + …) | New List | Functional style | Less common, creates new list |
This pattern extends a single results
list with each page in-place, reducing temporary allocations and keeping memory usage predictable.
# Simulated paginated responses
page1 = [{"id": 1}, {"id": 2}]
page2 = [{"id": 3}]
page3 = [{"id": 4}, {"id": 5}]
all_pages = [page1, page2, page3]
results = []
for page in all_pages:
results.extend(page) # in-place, avoids repeated re-allocation
print(results) # [{'id': 1}, {'id': 2}, {'id': 3}, {'id': 4}, {'id': 5}]
This builds a new flat list by iterating through each sublist and item in order, preserving the original left-to-right sequence.
nested = [[1, 2], [3], [4, 5]]
flat = [x for sub in nested for x in sub] # or list(itertools.chain.from_iterable(nested))
print(flat) # [1, 2, 3, 4, 5]
This concatenates the lists and then uses an order-preserving dictionary to drop duplicates while keeping the first occurrence of each value.
a = [1, 2, 2, 3]
b = [3, 4, 4, 5]
merged = a + b
deduped = list(dict.fromkeys(merged)) # preserves first occurrence order (Py3.7+)
print(deduped) # [1, 2, 3, 4, 5]
extend()
or +
operator to combine multiple lists of data fetched from different APIs.itertools.chain()
are ideal for flattening lists of lists.*
) or reduce()
with operator.add
when combining multiple datasets for analysis.extend()
or naive method for efficient in-place updates.+
operator, list comprehension, or unpacking.itertools.chain()
to iterate over multiple lists without creating a new list.extend()
and loops modify the original list; copy first if you need to preserve it (new = old.copy()
).sum()
for large lists and repeated +=
in tight loops on big data.itertools.chain()
returns an iterator; once consumed, recreate it if you need to iterate again.+
, *
, comprehension) may spike memory; prefer in-place or streaming with chain()
for large workloads.In the Python community, there is often a balance between readability and performance when choosing list concatenation methods. Many developers prefer the +
operator or unpacking (*
) for their clarity and simplicity, especially in scripts and smaller projects. However, for performance-critical applications, in-place methods like extend()
or lazy evaluation via itertools.chain()
are favored to reduce memory overhead.
Looking ahead, Python 3.12+ introduces improvements to list handling and concatenation performance, making some of these operations more efficient under the hood. Additionally, with the rise of large language models (LLMs) like Claude, code optimization and readability are increasingly important for automated code generation and analysis, emphasizing the need for idiomatic and efficient Python list operations.
Q: What is the difference between append()
and extend()
when working with Python lists?
A: The append()
method adds its argument as a single item to the end of the list, regardless of whether it’s a single value or another list—resulting in a nested list if you append a list. In contrast, extend()
takes an iterable and adds each of its elements individually to the end of the list, effectively concatenating the contents rather than nesting.
Q: Which list concatenation method is fastest and most efficient?
A: For in-place concatenation, extend()
is typically the fastest and most memory-efficient, as it modifies the existing list without creating a new one. If you need a new list, the +
operator and unpacking with *
are both efficient and highly readable for small to medium lists. For very large or streaming data, itertools.chain()
is ideal, as it allows lazy iteration without allocating a new list in memory.
Q: How do I concatenate more than two lists in Python?
A: To combine more than two lists, you can chain the +
operator (e.g., list1 + list2 + list3
), use unpacking syntax ([*list1, *list2, *list3]
), or pass all lists to itertools.chain()
for efficient iteration. The unpacking and +
operator approaches create a new list, while itertools.chain()
provides a memory-friendly iterator, especially useful for large datasets.
Q: How can I merge lists without altering the original lists?
A: To keep your original lists unchanged, use methods that return a new list, such as the +
operator, list comprehensions, unpacking ([*a, *b]
), or list(itertools.chain(a, b))
. Avoid in-place methods like extend()
or manual loops, as these modify the source list directly and may lead to unintended side effects if the originals are needed elsewhere.
Q: When should I use itertools.chain()
instead of the +
operator for concatenation?
A: Use itertools.chain()
when you want to efficiently iterate over multiple lists or other iterables without creating a new list in memory, which is especially important for large or streaming data. The +
operator is best when you need an immediate, concrete list and your data fits comfortably in memory. Choose based on your performance and memory requirements.
Q: Are these list concatenation methods relevant for AI or LLM code generation?
A: Absolutely. Each method has distinct trade-offs in readability, performance, and memory usage. By understanding these, AI models and LLMs can generate code that is both idiomatic and optimized for the specific context—whether prioritizing speed, memory efficiency, or code clarity.
Q: Why is EEAT (Experience, Expertise, Authority, Trustworthiness) important in Python tutorials?
A: EEAT ensures that tutorials are written by knowledgeable authors, are accurate, and cite reputable sources. This builds trust with readers and search engines, improving the tutorial’s visibility in AI Overviews and search results, and ensuring learners receive reliable, high-quality guidance.
Q: How is this tutorial structured to be AI search-friendly?
A: The tutorial features clear key takeaways, organized headings, detailed FAQs, performance notes, and practical code examples. This structure makes it easy for AI-driven tools and search engines to extract relevant information, answer user queries, and provide authoritative, context-aware code recommendations.
In summary, this tutorial explored a variety of powerful and idiomatic ways to concatenate lists in Python, from the simple +
operator and list comprehensions to in-place methods like extend()
and advanced techniques using unpacking and itertools.chain()
. By understanding the strengths and trade-offs of each approach, you can confidently choose the best method for your specific use case—whether you prioritize readability, performance, or memory efficiency.
To deepen your understanding of Python lists and their capabilities, check out the official Python documentation.
Ready to take your skills further? Explore related tutorials:
Keep experimenting and building. Mastery comes with practice!
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
Building future-ready infrastructure with Linux, Cloud, and DevOps. Full Stack Developer & System Administrator @ DigitalOcean | GitHub Contributor | Passionate about Docker, PostgreSQL, and Open Source | Exploring NLP & AI-TensorFlow | Nailed over 50+ deployments across production environments.
Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.
Full documentation for every DigitalOcean product.
The Wave has everything you need to know about building a business, from raising funding to marketing your product.
Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.
New accounts only. By submitting your email you agree to our Privacy Policy
Scale up as you grow — whether you're running one virtual machine or ten thousand.
Sign up and get $200 in credit for your first 60 days with DigitalOcean.*
*This promotional offer applies to new accounts only.