How To Append A List To A List In Python

8 min read

Appending a list to another list is one of the most fundamental operations in Python programming, yet it is also a common source of confusion for beginners. Which means the core of the confusion lies in the distinction between adding a list as a single element versus merging the contents of one list into another. Understanding this difference is critical for data manipulation, algorithm implementation, and avoiding subtle bugs that can corrupt data structures. This guide explores every standard method to combine lists in Python, explaining the syntax, performance implications, and the specific use case for each approach Worth keeping that in mind..

The Fundamental Distinction: Nested vs. Flat

Before diving into syntax, you must visualize the desired outcome. There are two distinct results when combining list_a and list_b:

  1. Nested List (List of Lists): list_a becomes [[1, 2], [3, 4]]. The second list exists as a single item inside the first.
  2. Flat List (Extended List): list_a becomes [1, 2, 3, 4]. The elements of the second list are unpacked and added individually to the first.

Choosing the wrong method leads to structural errors downstream, such as iteration failures or TypeError exceptions when code expects integers but finds lists.

Method 1: The append() Method (Creates Nesting)

The append() method is the most direct way to add a single object to the end of a list. When that object is another list, Python treats the entire list argument as one single element And it works..

primary_list = [1, 2, 3]
secondary_list = [4, 5, 6]

primary_list.append(secondary_list)

print(primary_list)
# Output: [1, 2, 3, [4, 5, 6]]
print(len(primary_list))
# Output: 4 (not 6)

Key Characteristics:

  • Mutates in-place: It modifies primary_list directly and returns None.
  • Increases length by 1: Regardless of how many items are in secondary_list, the length of primary_list increases by exactly one.
  • Use Case: Building matrices, trees, or any hierarchical data structure where you need to preserve the grouping of the sub-list.

Method 2: The extend() Method (Creates Flat List)

If your goal is to merge the contents of two lists into a single, flat sequence, extend() is the idiomatic, built-in solution. It iterates over the argument (any iterable) and appends each item individually Easy to understand, harder to ignore..

primary_list = [1, 2, 3]
secondary_list = [4, 5, 6]

primary_list.extend(secondary_list)

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

Key Characteristics:

  • Mutates in-place: Like append(), it modifies the original list and returns None.
  • Accepts any iterable: You can pass tuples, sets, strings, or generators, not just lists.
  • Performance: Highly optimized in CPython. It is generally the fastest way to concatenate lists in-place because it resizes the underlying array once (or logarithmically) rather than per element.

Method 3: The + Operator (Creates a New List)

The concatenation operator + creates a brand new list object containing the elements of both operands. It does not modify the original lists. This is crucial for functional programming styles or when you need to preserve the original data structures Nothing fancy..

list_a = [1, 2, 3]
list_b = [4, 5, 6]

combined_list = list_a + list_b

print(combined_list)
# Output: [1, 2, 3, 4, 5, 6]
print(list_a)      # Unchanged: [1, 2, 3]
print(list_b)      # Unchanged: [4, 5, 6]

Key Characteristics:

  • Immutability of originals: list_a and list_b remain untouched.
  • Memory Overhead: Requires allocating memory for the new list and copying references from both sources. For massive lists, this doubles memory usage temporarily.
  • Chaining: Allows clean chaining: result = list_a + list_b + list_c.

Method 4: The += Operator (In-Place Augmented Assignment)

The += operator behaves similarly to extend() but with a critical syntactic nuance. It modifies the list in-place (like extend) rather than creating a new object (like +).

list_a = [1, 2, 3]
list_b = [4, 5, 6]

list_a += list_b  # Equivalent to list_a.extend(list_b)

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

Critical Nuance — Variable Binding:

# Scenario A: Using +
a = [1, 2]
b = a
a = a + [3, 4]  # 'a' now points to a NEW list object
print(b)        # Output: [1, 2] (b still points to the old object)

# Scenario B: Using +=
x = [1, 2]
y = x
x += [3, 4]     # 'x' is modified IN-PLACE
print(y)        # Output: [1, 2, 3, 4] (y reflects the change because it's the same object)

This distinction is vital when multiple variables reference the same list object.

Method 5: Unpacking with the * Operator (Python 3.5+)

Introduced in PEP 448, the unpacking operator * provides a modern, readable syntax for creating new lists from multiple iterables. It is highly expressive and works inside list literals Simple, but easy to overlook..

list_a = [1, 2, 3]
list_b = [4, 5, 6]

# Creating a new list
combined = [*list_a, *list_b]
print(combined) # Output: [1, 2, 3, 4, 5, 6]

# Inserting in the middle
mixed = [0, *list_a, 99, *list_b, 100]
print(mixed)    # Output: [0, 1, 2, 3, 99, 4, 5, 6, 100]

Advantages:

  • Readability: Visually clear that unpacking is happening.
  • Flexibility: Allows interleaving elements from different sources easily.
  • Versatility: Works with any iterable (generators, tuples, sets) without friction.

Method 6: itertools.chain() (Memory Efficient for Iteration)

When dealing with massive datasets where creating a combined list in memory is prohibitive, itertools.chain is the professional choice. It returns an iterator that yields elements from the first iterable until exhausted, then proceeds to the next.

import itertools

list_a = [1, 2, 3]
list_b = [4, 5, 6]

# Returns an iterator, not a list
chained_iterator = itertools.chain(list_a, list_b)

# Consume the iterator
for item in chained_iterator:
    print(item, end=" ") # Output: 1 2 3 4 5 6

# If you actually need a list object eventually:
combined_list = list(itertools.chain(list_a, list_b))

Use Case: Processing large log files

...or streaming data from network sockets where loading the entire concatenated result into RAM is unnecessary or impossible. Since chain evaluates lazily, it maintains a constant memory footprint (O(1)) regardless of the input sizes.

Advanced Variant — itertools.chain.from_iterable: If your input is a list of lists (or an iterable of iterables), this variant flattens one level of nesting efficiently No workaround needed..

nested = [[1, 2], [3, 4], [5, 6]]
flat = list(itertools.chain.from_iterable(nested))
# Output: [1, 2, 3, 4, 5, 6]

Method 7: List Comprehensions (Flattening & Filtering)

While typically used for transformation, list comprehensions are a Pythonic "swiss army knife" for concatenation when you need to flatten a sequence of sequences or filter elements during the merge And that's really what it comes down to..

lists = [[1, 2], [3, 4], [5, 6]]

# Flattening (equivalent to chain.from_iterable)
flat = [item for sublist in lists for item in sublist]

# Conditional Concatenation: Merge only lists with length > 1
data = [[1], [2, 3], [4], [5, 6, 7]]
filtered_merge = [item for sublist in data if len(sublist) > 1 for item in sublist]
print(filtered_merge) # Output: [2, 3, 5, 6, 7]

Note: For simple flattening of massive lists, itertools.chain is faster; for logic-heavy merging, comprehensions win on readability.

Method 8: The sum() "Trick" (Use with Caution)

A lesser-known idiom uses the built-in sum() function with an empty list as the start value.

lists = [[1, 2], [3, 4], [5, 6]]
combined = sum(lists, []) 
# Output: [1, 2, 3, 4, 5, 6]

⚠️ Performance Warning: This is O(N²) complexity. Because sum performs repeated + operations (creating a new list copy at every step), it becomes catastrophically slow as the number of lists or total elements grows. Avoid in production code for anything beyond tiny datasets.


Performance Benchmark: Choosing the Right Tool

The "best" method depends entirely on your constraints: Memory, Mutability requirements, and Input Structure The details matter here..

Benchmark Scenario: Concatenating 100 lists of 10,000 integers each (1M total items).

| Method | Time Complexity | Space Complexity | Mutates Original? | | + Operator | O(N) per op | O(N) per op | No | Simple scripts, chaining 2-3 small lists. | | * Unpacking | O(N) | O(N) (New List) | No | Modern, readable creation of new lists; mixing iterables. On top of that, | | itertools. Still, | | **List Comprehension** | **O(N)** | **O(N)** (New List) | No | Flattening + Filtering/Transformation logic. | Best For | | :--- | :--- | :--- | :--- | :--- | | **extend()/+=** | **O(N)** (Fastest) | **O(1)** Auxiliary | **Yes** | High-performance in-place modification. chain | O(1) Setup / O(N) Iter | O(1) (Iterator) | No | Massive data, streaming, memory constraints. | | sum(lists, []) | O(N²) | O(N²) Copies | No | Never (Educational curiosity only).

Key Takeaways from Benchmarks:

  1. In-place (extend / +=) is consistently the raw speed winner because it avoids allocation overhead.
  2. Unpacking (*) is highly optimized in CPython (often using LIST_EXTEND bytecode internally) and is the preferred "Pythonic" way to create a new list in 3.5+.
  3. itertools.chain has near-zero startup cost; the cost is paid during iteration.

Decision Matrix: Which One Do I Use?

If your situation is... Use this method.
"I have a huge list A and want to append B to it right now, no copies." A.extend(B) or A += B
"I need a brand new list C containing A + B; A and B must stay untouched.
Newest Stuff

Just Dropped

Readers Also Checked

Follow the Thread

Thank you for reading about How To Append A List To A 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