How To Concatenate List In Python

10 min read

How to Concatenate Lists in Python

Concatenating lists in Python is a fundamental operation that many developers encounter early in their programming journey. Whether you're building a data processing pipeline, combining user inputs, or merging datasets for analysis, knowing how to join two or more lists is an essential skill. In this full breakdown, we'll explore the various methods available for concatenating lists in Python, understand when each approach is most appropriate, and learn best practices to ensure your code remains efficient and readable And that's really what it comes down to..

Understanding Lists in Python

Before diving into concatenation techniques, you'll want to grasp what a list is in Python. And a list is an ordered, mutable sequence that can hold multiple items of various data types. And lists are built using square brackets [] and can contain elements of different types, such as integers, strings, booleans, or even other lists. One of the most common operations with lists is concatenation—the process of joining two or more lists into a single, unified list.

Python offers several built-in ways to achieve this, each with its own advantages and use cases. Understanding these methods will help you make informed decisions based on your specific requirements for performance, readability, and functionality.

Methods for Concatenating Lists in Python

There are multiple approaches to concatenate lists in Python, and each has its own strengths depending on your use case. Let's explore the most common techniques Worth knowing..

Using the + Operator

The simplest and most widely used method for concatenating lists in Python is the + operator. This operator performs element-wise concatenation, creating a new list that contains all elements from both original lists in order Simple as that..

list1 = [1, 2, 3]
list2 = [4, 5, 6]
combined = list1 + list2
print(combined)  # Output: [1, 2, 3, 4, 5, 6]

The + operator is straightforward and works well for small to medium-sized lists. It creates a new list rather than modifying the original lists, which is generally desirable since lists are mutable and you often want to preserve the original data.

When to use the + operator:

  • When you need a new concatenated list without modifying the originals
  • For simple, one-time concatenation tasks
  • When readability is a priority

Performance considerations:

  • The + operator has a time complexity of O(n + m), where n and m are the lengths of the two lists
  • It creates a new list, which can be memory-intensive for very large lists
  • If you're concatenating many lists repeatedly, this approach may become inefficient

Using the extend() Method

The extend() method is another powerful tool for list concatenation. Unlike the + operator, which creates a new list, extend() modifies the original list in place by adding all elements from another iterable (such as another list) to its end.

list1 = [1, 2, 3]
list2 = [4, 5, 6]
list1.extend(list2)
print(list1)  # Output: [1, 2, 3, 4, 5, 6]

When to use extend():

  • When you want to modify an existing list rather than creating a new one
  • When memory efficiency is a concern since it avoids creating a duplicate copy
  • When working with large datasets where minimizing memory allocation is important

Performance considerations:

  • extend() is generally more memory-efficient than + because it doesn't create a new list
  • It operates in O(m) time complexity where m is the length of the list being extended
  • The original list is modified, so use it when you don't need to preserve the initial state

Using the list() Constructor

Another approach involves using the list() constructor with the extend() method. This technique is particularly useful when you need to combine multiple iterables into a single list Simple, but easy to overlook..

list1 = [1, 2, 3]
list2 = [4, 5, 6]
combined = list(list1 + list2)
print(combined)  # Output: [1, 2, 3, 4, 5, 6]

While this method works, it's essentially combining two steps—first concatenating with +, then converting to a list—which is less efficient than using extend() directly.

When to use the list() constructor:

  • When you're already working with an iterable and need to convert it to a list while concatenating
  • For educational purposes to understand different Python constructs

Performance considerations:

  • This approach is less efficient than using + or extend() directly
  • It creates an intermediate concatenated list before converting, increasing memory usage

Using itertools.chain()

For advanced use cases where you're dealing with multiple lists or iterables, the itertools.chain() function provides a flexible and memory-efficient solution. This function returns an iterator that yields elements from each iterable in turn, allowing you to chain multiple lists together without creating a new list in memory.

import itertools

list1 = [1, 2, 3]
list2 = [4, 5, 6]
list3 = [7, 8, 9]

combined = list(itertools.chain(list1, list2, list3))
print(combined)  # Output: [1, 2, 3, 4, 5, 6, 7, 8, 9]

When to use itertools.chain():

  • When working with more than two lists simultaneously
  • When memory efficiency is critical (the generator approach doesn't create intermediate lists)
  • When you want to avoid modifying the original lists entirely

Performance considerations:

  • Excellent for large datasets since it generates elements on-the-fly
  • Converts the final result to a list only when needed
  • Slightly more complex to use compared to basic operators

Practical Examples

To solidify your understanding, let's look at some practical examples demonstrating each method.

Example 1: Basic Concatenation with + Operator

# Creating two separate lists
fruits = ["apple", "banana", "cherry"]
vegetables = ["carrot", "broccoli", "spinach"]

# Concatenating using the + operator
combined_fruits_veggies = fruits + vegetables
print(combined_fruits_veggies)
# Output: ['apple', 'banana', 'cherry', 'carrot', 'broccoli', 'spinach']

Example 2: Modifying Original List with extend()

# Start with an empty list
numbers = [1, 2, 3]

# Add another list using extend()
other_numbers = [4, 5, 6]
numbers.extend(other_numbers)

print(numbers)  # Output: [1, 2, 3, 4, 5, 6]

Example 3: In‑place modification vs. creating a new list

When the original list must stay unchanged, using + or the unpacking operator creates a fresh list, leaving the source untouched The details matter here. But it adds up..

original = ['red', 'green']
copy = original + ['blue', 'yellow']
print(original)   # ['red', 'green']
print(copy)       # ['red', 'green', 'blue', 'yellow']

If you need to augment the list without allocating a new object, extend() is the idiomatic choice:

original = ['red', 'green']
original.extend(['blue', 'yellow'])
print(original)   # ['red', 'green', 'blue', 'yellow']

The difference becomes noticeable when the list is large; extend() avoids the temporary allocation that + would incur Practical, not theoretical..

Example 4: Using the unpacking operator (*) for concatenation

Python 3.5+ introduced the * operator for sequence unpacking, which can be handy when you already have the lists as variables:

a = [1, 2]
b = [3, 4]
c = [*a, *b]          # equivalent to a + b, but more readable in some contexts
print(c)              # [1, 2, 3, 4]

Unlike +, the unpacking form does not create an intermediate list before the list() call; it builds the result directly, offering a modest performance gain for medium‑sized collections Which is the point..

Example 5: Merging many iterables with itertools.chain in a loop

When the number of iterables is not known ahead of time, itertools.chain.from_iterable can consume an iterable of iterables and yield a single stream:

import itertools

lists = [[10, 20], [30], [40, 50, 60]]

# The generator expression wraps each inner list, allowing chain to handle any number of them
merged = list(itertools.chain.from_iterable(lists))
print(merged)   # [10, 20, 30, 40, 50, 60]

This pattern eliminates the need to list each iterable explicitly, making the code adaptable to dynamically generated collections.

Example 6: Combining lists inside a function without side effects

If a function should return a combined list while preserving the arguments, it is safest to work on a copy:

def merge_lists(a, b):
    # Work on a shallow copy so the callers' lists stay unchanged
    result = a.copy()
    result.extend(b)
    return result

first = [1, 2]
second = [3, 4]
combined = merge_lists(first, second)
print(combined)   # [1, 2, 3, 4]
print(first, second)  # [1, 2] [3, 4]  (unchanged)

Using extend() on a copy guarantees that the original data structures are left untouched, which is crucial in APIs that must be pure functions.

Performance snapshot

Technique Memory overhead Typical use case
+ (or list(a + b)) Creates a new list plus a temporary concatenated list Small‑to‑medium lists, quick one‑off merges
extend() Modifies in place, no extra allocation When you need to grow an existing list or avoid extra memory
* unpacking Builds result directly, minimal temporaries Readable syntax for a handful of lists
itertools.chain / chain.from_iterable Produces a lazy iterator; materializes only when list() is called Large or numerous iterables, memory‑critical pipelines

When to choose which approach

  • Small, static collections – the + operator is concise and perfectly adequate.
  • Large collections or tight memory budgets – prefer extend() or a lazy iterator from itertools.
  • Dynamic numbers of iterables – itertools.chain.from_iterable or a loop that repeatedly extend()s.
  • Functional style (no side effects) – work on a copy (a.copy() or list(a)) and then

Functional style (no side effects) – work on a copy (a.copy() or list(a)) and then return the result, ensuring that the original data remain pristine. This pattern is especially valuable in concurrent programs or when integrating with libraries that expect immutable inputs.

Another popular technique is the * unpacking operator, which was introduced in Python 3.5 and provides a concise way to merge multiple iterables in a single expression:

lists = [[10, 20], [30], [40, 50, 60]]
merged = [x for sublist in lists for x in sublist]
print(merged)   # [10, 20, 30, 40, 50, 60]

While this syntax is elegant for a small number of collections, it quickly becomes unwieldy when the number of iterables grows. And from_iterableapproach for large datasets. chain.The resulting list comprehension creates a new list by iterating through each sublist, which can be less memory-efficient than the lazyitertools.On the flip side, for code readability and when the number of lists is fixed and known, it remains a powerful tool No workaround needed..

Choosing the Right Tool for the Job

Understanding the trade-offs between these methods is essential for writing maintainable and performant code. The decision should be guided by three primary factors:

  1. Data size and memory constraints – For modest collections, the simplicity of the + operator or list concatenation is often sufficient. When dealing with millions of elements or streaming data, lazy evaluation via itertools.chain or generator expressions prevents excessive memory consumption.
  2. Immutability requirements – If your functions must be pure and cannot modify their inputs, always create a shallow or deep copy before manipulation. This practice safeguards against unintended side effects, particularly in larger codebases where traceability of state changes is critical.
  3. Dynamic versus static inputs – When the number of iterables is predetermined and small, the * unpacking pattern or even nested loops with extend() can improve readability. Conversely, when iterables are generated on the fly or their count is unknown, itertools.chain.from_iterable shines by deferring computation until absolutely necessary.

Practical Recommendations

  • Avoid implicit mutation – Prefer built‑in methods like list.copy(), dict.copy(), and set.copy() when you need to work on a subset of data without altering the original. This aligns with the principle of least surprise and makes code easier to debug.
  • make use of lazy evaluation – In data‑processing pipelines, chaining operations with itertools or using generator functions allows you to process records one at a time, keeping memory footprints low.
  • Profile your code – If performance becomes an issue, benchmark different approaches under realistic workloads. The performance table earlier shows that + creates temporary objects, while extend() and chain.from_iterable minimize allocations.

Conclusion

Merging and combining collections in Python is a nuanced task that benefits from selecting the right tool for each scenario. from_iterableprovides memory efficiency and flexibility for dynamic or large datasets; and* unpacking delivers readable, declarative code for a limited number of iterables. Plus, chain. So copy() combined with extend() ensures functional purity when side effects must be avoided; itertools. The +operator offers brevity for small, static lists;list.This leads to by consciously matching these techniques to the characteristics of your data and functional requirements, you can write code that is not only correct but also performant and maintainable. In the long run, the goal is to balance simplicity, performance, and clarity—choosing the method that best serves the problem at hand while keeping the code clean and understandable.

Brand New

New Arrivals

More of What You Like

Before You Head Out

Thank you for reading about How To Concatenate List In Python. We hope the information has been useful. Feel free to contact us if you have any questions. See you next time — don't forget to bookmark!
⌂ Back to Home