Back to Blog
Python

Python list append: Usage, Behavior, and Performance

python list append: Learn how Python's list.append() works, its return value, time complexity, common mistakes, and when to use alternatives like extend.

Pythonlist methodsdata structuresperformancecode examples
Illustration of a Python list with an element being appended at the end.

python list append requires a clear understanding of the core syntax, runtime behavior, and practical implementation patterns demonstrated in the examples below.

Python's list.append() is the most direct way to add a single element to the end of a list. It modifies the list in place, returns None, and runs in amortized O(1) time. This behavior makes it the preferred choice for building lists incrementally, but it also leads to several common mistakes when developers expect a new list or confuse it with extend().

The append Method and Its Return Value

append() is a method on the list type. It takes one argument and adds that argument as a single element to the end of the list. The method returns None, not the modified list. This is a frequent point of confusion, especially for developers coming from languages where mutating methods return the original object for chaining.

numbers = [1, 2, 3] result = numbers.append(4) print(numbers) # [1, 2, 3, 4] print(result) # None

Because append() returns None, you cannot chain it like list.append(5).append(6). If you need to chain, you must call append() separately or use a different approach.

How append Affects the Original List

append() mutates the list in place. It does not create a copy. Any variable that references the same list object will see the change. This is important when you pass a list to a function and append inside that function.

def add_item(items, item): items.append(item) cart = [] add_item(cart, "apple") print(cart) # ['apple']

The function modifies the original list, so the caller sees the updated state. If you need to avoid modifying the original list, you must create a copy first, for example with items.copy() or items[:], before calling append().

Time Complexity and Memory Allocation

The time complexity of append() is amortized O(1). In practice, the operation is very fast because it only adds a reference to the end of the underlying array. However, Python's list is implemented as a dynamic array, which means it occasionally needs to allocate a larger block of memory and copy existing elements when the capacity is exceeded. This reallocation is amortized over many appends, so the average cost per operation stays constant.

Memory usage is also worth considering. When a list grows, Python may overallocate capacity to reduce the frequency of reallocations. This means a list can use more memory than the exact size of its elements. The exact overallocation strategy is an implementation detail and can change between Python versions, but the general behavior is that appending many elements is efficient in both time and space.

For most applications, append() is the right choice for building a list incrementally. If you know the final size in advance, preallocating with [None] * n and assigning by index can avoid reallocations, but it is rarely necessary unless you are working with very large collections and have measured a bottleneck.

Common Mistakes: append vs extend

A frequent error is using append() when you actually want to add multiple elements from an iterable. append() adds the iterable as a single element, while extend() adds each element individually.

numbers = [1, 2] more = [3, 4] numbers.append(more) print(numbers) # [1, 2, [3, 4]] numbers = [1, 2] numbers.extend(more) print(numbers) # [1, 2, 3, 4]

If you use append() with a list, you get a nested list. This is often not what you intended. extend() is the correct method when you want to merge an iterable into the existing list. The same distinction applies to strings: append("abc") adds the string as one element, while extend("abc") adds the characters 'a', 'b', and 'c' separately.

Appending in Loops: When to Use append

append() is commonly used inside loops to collect results. Because it is amortized O(1), it is efficient even for large loops. A typical pattern is:

squares = [] for n in range(10): squares.append(n ** 2)

This is clear and idiomatic. A list comprehension is often more concise for simple transformations, but append() gives you more flexibility when the logic is complex or when you need to conditionally add elements.

filtered = [] for value in source: if value > 0: filtered.append(value)

In such cases, append() is the natural choice. Avoid using append() in a loop when you can use a list comprehension or extend() with a generator expression, but do not sacrifice readability for micro-optimizations.

Edge Cases: Appending While Iterating

Modifying a list while iterating over it is dangerous. If you append to a list inside a for loop that iterates over the same list, the loop may never terminate or may skip elements because the list's length changes during iteration.

# This loop will run indefinitely in CPython items = [1, 2, 3] for item in items: items.append(item)

The loop keeps finding new items because the iterator reads the current length at each step. To avoid this, iterate over a copy of the list or collect new items in a separate list and extend the original after the loop.

items = [1, 2, 3] new_items = [] for item in items: if item < 3: new_items.append(item * 10) items.extend(new_items)

This pattern is safe and clear. Appending to a list while iterating over a different list is perfectly fine.

Alternatives to append: extend, +=, and List Comprehensions

extend() is the primary alternative when you need to add multiple elements. The += operator on a list is equivalent to extend(): it mutates the list in place and adds all elements from the right-hand iterable.

a = [1, 2] a += [3, 4] print(a) # [1, 2, 3, 4]

List comprehensions are a declarative way to build a new list without explicitly calling append(). They are often faster and more readable for simple transformations, but they always create a new list, so they are not a drop-in replacement when you need to mutate an existing list.

Method/OperatorAdds single elementAdds multiple elementsReturns new listMutates in place
append()YesNoNoYes
extend()NoYesNoYes
+=NoYesNoYes
List comprehensionNoYesYesNo

Choose append() when you have one element to add. Use extend() or += when you have an iterable. Use a list comprehension when you are building a new list from an existing iterable and the transformation is simple enough to express in one expression.

Memory and Capacity: What Happens Under the Hood

When a list grows, CPython's list implementation may allocate more memory than immediately needed to reduce the cost of future reallocations. This overallocation is why append() is amortized O(1). If you append a large number of elements, the list will occasionally resize, copying references to the new storage. This copying is fast because it only moves pointers, not the objects themselves.

If you are concerned about memory usage, note that append() does not copy the element you add; it stores a reference. For immutable objects like integers or strings, this is usually irrelevant. For mutable objects, be aware that the list holds a reference, so later modifications to the object will be visible in the list.

In long-running applications that build large lists, you may want to periodically trim excess capacity. Python does not expose a direct method to shrink a list's capacity, but you can create a new list with list(existing) or use slicing to copy the elements. This is rarely needed unless you are holding a list that grew temporarily and you want to free memory before keeping it around.

Understanding append()'s behavior, return value, and performance characteristics helps you write correct and efficient Python code. The method is simple, but its nuances affect how you structure loops, handle mutable state, and choose between similar operations.

python list append: Practical Usage and Code Examples | RYUSLOG DEV