Quick answer: Assignment creates another reference to a list. Use slicing, list(), or copy() for a shallow copy of the outer list, and use copy.deepcopy only when nested mutable objects must be independent and the ownership and performance costs are understood.

To copy a list in Python, use list.copy(), slicing, or list() for a shallow copy. Use copy.deepcopy() only when the list contains nested mutable objects and you need the nested objects copied too.
copied = original.copy()
Assignment does not copy a list
The = operator does not copy a list. It creates another name for the same list object. If you mutate the alias, the original changes too.
numbers = [1, 2, 3]
alias = numbers
alias.append(4)
print(numbers)
Output:
[1, 2, 3, 4]
Use assignment when you intentionally want two names pointing to the same list. Use a copy method when you want a separate list container.
Copy a list with list.copy()
list.copy() is the clearest way to make a shallow copy of a list in modern Python.
numbers = [1, 2, 3]
copied = numbers.copy()
copied.append(4)
print(numbers)
print(copied)
Output:
[1, 2, 3]
[1, 2, 3, 4]
The copied list gets the appended value, while the original list remains unchanged.
Copy a list with slicing
Slicing the whole list with [:] creates the same kind of shallow copy. You will still see this pattern in many Python codebases.
numbers = [1, 2, 3]
copied = numbers[:]
print(copied)
Use numbers.copy() when readability matters most, and numbers[:] when you are already working with slices.

Copy a list with list()
The list() constructor also creates a new list from an iterable. It is useful when the source might be another iterable, such as a tuple, generator, or dictionary view.
numbers = [1, 2, 3]
copied = list(numbers)
print(copied)
For an existing list, numbers.copy(), numbers[:], and list(numbers) all create a shallow copy.
Shallow copy vs deep copy
A shallow copy creates a new outer list, but it keeps references to the same nested objects. This matters for lists of lists.
matrix = [[1, 2], [3, 4]]
shallow = matrix.copy()
shallow[0].append(99)
print(matrix)
print(shallow)
Output:
[[1, 2, 99], [3, 4]]
[[1, 2, 99], [3, 4]]
The outer list is new, but the first inner list is shared. Mutating that inner list appears in both variables.
Copy nested lists with deepcopy()
Use copy.deepcopy() when you need independent nested lists.
from copy import deepcopy
matrix = [[1, 2], [3, 4]]
deep = deepcopy(matrix)
deep[0].append(99)
print(matrix)
print(deep)
Output:
[[1, 2], [3, 4]]
[[1, 2, 99], [3, 4]]
deepcopy() recursively copies contained objects. It is the right tool for nested mutable data, but it can be slower and may copy more than you need for large object graphs.
Use list comprehension when changing values
If you want a transformed list, use a list comprehension instead of copying and then editing each item.
To transform conditionally while preserving or reducing the list length, compare the filter and replacement forms in Python list comprehension with if/else.
numbers = [1, 2, 3]
squares = [number ** 2 for number in numbers]
print(squares)
This creates a new list with squared values. The original list is not changed.

Avoid repeated nested list traps
The multiplication operator can repeat references to the same nested list. Use a list comprehension when creating independent nested lists.
bad_grid = [[0] * 3] * 2
bad_grid[0][0] = 1
print(bad_grid)
good_grid = [[0] * 3 for _ in range(2)]
good_grid[0][0] = 1
print(good_grid)
The first grid shares the same inner list twice. The second grid creates a new inner list for each row. For more nested-list examples, see our Python 2D list guide.
Which method should you use?
old.copy(): best default for copying a normal list.old[:]: fine for shallow copies, especially in slice-heavy code.list(old): useful when the source may be any iterable.deepcopy(old): use for nested mutable data that must be independent.- List comprehension: use when you want to transform values while building a new list.
Common mistakes
- Using
=and expecting a copy: assignment creates an alias, not a new list. - Expecting shallow copy to clone nested lists: shallow copy only copies the outer list container.
- Using
append()to copy one list into another: that nests the list. Useextend()or a copy method depending on the goal. - Using
*for nested lists:[[0] * 3] * 2repeats the same inner list reference. - Deep copying everything by default:
deepcopy()is powerful, but unnecessary for simple flat lists.

Related Python guides
- Python 2D list
- append() vs extend() in Python
- Convert dictionary to list in Python
- Fix TypeError: unhashable type: ‘list’
- Append strings in Python
- Python range() inclusive
Official references
- Python tutorial: list methods
- Python documentation: copy module
- Python documentation: mutable sequence types
Conclusion
Use my_list.copy() when you need a straightforward shallow copy of a list. Use slicing or list() when they fit the surrounding code, and switch to deepcopy() only when nested mutable objects must be copied independently.
Recognize Aliases
If two names point to the same list, append, remove, or item assignment through either name changes the same object. Check identity with is when diagnosing this behavior.
Make A Shallow Copy
list_value.copy(), list(list_value), and list_value[:] create a new outer list. Elements remain shared references, which is correct for immutable elements and sometimes intended for objects with shared ownership.
Handle Nested Lists
A shallow copy of [[1]] still shares the inner list. Mutating that nested value changes both outer lists, so copy the nested structure only when the data contract requires independent ownership.

Use Deepcopy Carefully
copy.deepcopy recursively copies supported objects and tracks cycles, but custom resources, locks, caches, file handles, and large graphs may not have meaningful or efficient deep-copy behavior.
Prefer Explicit Construction
For a known schema, a comprehension or constructor can copy exactly the fields needed and avoid copying accidental state. This is often clearer than a blanket deep copy.
Test Identity And Values
Test empty and nested lists, aliases, immutable elements, shallow changes, deep changes, custom objects, cycles, and performance before selecting the copy strategy.
Use the official Python copy documentation. Related Python Pool references include Python lists and testing.
For related collection semantics, compare list operations, nested mappings, and identity tests before copying state.
Frequently Asked Questions
How do I make a shallow copy of a Python list?
Use list_value.copy(), list(list_value), or list_value[:] when an independent outer list with shared element references is the intended result.
When should I use deepcopy?
Use copy.deepcopy when nested mutable objects must also be copied, after considering custom objects, resources, cycles, and the cost of recursive copying.
Why did changing the copied list change the original?
The variables may reference the same list, or a shallow copy may still share a nested list or dictionary.
Is assignment a list copy?
No. Assignment creates another reference to the same list; it does not create a new container.