Python’s list is what most people mean by “array”. This guide covers the errors that stop you and the handful of changes that genuinely make list code faster.
Error 1: IndexError#
items = ["a", "b", "c"]
print(items[3]) # IndexError: list index out of rangePositions start at 0, so the last item is at len(items) - 1. Two fixes depending on what you meant:
print(items[-1]) # "c" — last item, no arithmetic needed
if items: # guard against an empty list
print(items[0])Slices never raise this — items[1:99] quietly gives you what exists. Single indexes do.
Error 2: modifying while looping#
This one does not crash. It silently skips items, which is worse.
numbers = [1, 2, 4, 6, 7]
for n in numbers:
if n % 2 == 0:
numbers.remove(n) # removes 2, then SKIPS 4
print(numbers) # [1, 4, 7] — 4 survivedRemoving an item shifts everything left while the loop’s internal counter keeps advancing, so it jumps over the next element. Build a new list instead:
numbers = [n for n in numbers if n % 2 != 0]Error 3: the copy trap#
original = [1, 2, 3]
backup = original
backup.append(4)
print(original) # [1, 2, 3, 4] — not a backup at allAssigning gives you a second name for the same list. For a real copy:
backup = original.copy() # or list(original), or original[:]Note that a copy of a list of lists still shares the inner lists. Use copy.deepcopy() when that matters.
Error 4: sort returns None#
numbers = [3, 1, 2]
numbers = numbers.sort() # numbers is now None
print(numbers) # Nonesort() reorders the list in place and returns nothing. Either call it on its own line, or use sorted() which returns a new list:
numbers.sort() # in place
ordered = sorted(numbers) # new list, original untouchedEfficiency: what actually matters#
Searching a large list repeatedly#
This is the one worth knowing. x in a_list checks every item, so doing it inside a loop is slow on large data.
allowed = ["a", "b", "c", ...] # thousands of items
for item in huge_list:
if item in allowed: # scans the whole list every time
...
allowed = set(allowed) # convert once
for item in huge_list:
if item in allowed: # near-instant regardless of size
...On big data this is the difference between seconds and minutes.
Appending versus inserting at the front#
items.append(x) # fast
items.insert(0, x) # slow — every other item shifts alongIf you genuinely need to add at the front repeatedly, use collections.deque, which is built for it.
Building strings from a list#
result = ""
for word in words:
result += word # creates a new string every time
result = "".join(words) # one operationComprehensions over manual loops#
doubled = []
for n in numbers:
doubled.append(n * 2)
doubled = [n * 2 for n in numbers] # shorter and slightly fasterUseful things you can ask a list#
numbers = [4, 9, 2, 7]
len(numbers) # 4
sum(numbers) # 22
max(numbers) # 9
min(numbers) # 2
sorted(numbers) # [2, 4, 7, 9]
2 in numbers # True
numbers.count(4) # 1
numbers.index(9) # 1Questions people ask#
Should I use a real array instead of a list?
Python’s array module and NumPy arrays hold one type and use less memory, which matters for large numeric data. For everyday work a list is the right choice.
How do I remove duplicates?
list(set(items)) is quickest but loses the order. list(dict.fromkeys(items)) keeps it.
Why is my sort putting uppercase first?
Sorting compares character codes and uppercase letters come first. Use sorted(words, key=str.lower).
What is the difference between remove, pop and del?
remove(value) deletes by value, pop(index) deletes by position and returns the item, del items[i] deletes by position and returns nothing.