Follow AiTechWorlds on LinkedIn for professional AI content!Follow Now →
20 minLesson 7 of 34
Data Structures

Lists: The Ultimate Guide

Lists: The Ultimate Guide

Lists are Python's workhorse data structure. If you only master one data structure in Python, make it lists. They're used everywhere — storing results, processing data, managing state, and building every other structure.

Creating Lists

# Empty list
empty = []

# List of values
numbers = [1, 2, 3, 4, 5]
names = ["Alice", "Bob", "Carol"]
mixed = [1, "hello", True, 3.14, None]

# From a range
digits = list(range(10))          # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
even = list(range(0, 20, 2))      # [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

# Nested lists (2D data)
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
print(matrix[1][2])    # 6 — row 1, column 2

Indexing and Slicing

fruits = ["apple", "banana", "cherry", "date", "elderberry"]

# Indexing (0-based, negative from end)
print(fruits[0])    # "apple"
print(fruits[-1])   # "elderberry"
print(fruits[-2])   # "date"

# Slicing [start:stop:step]
print(fruits[1:3])   # ["banana", "cherry"]  — stop is exclusive
print(fruits[:3])    # ["apple", "banana", "cherry"]
print(fruits[2:])    # ["cherry", "date", "elderberry"]
print(fruits[::2])   # ["apple", "cherry", "elderberry"]  — every 2nd
print(fruits[::-1])  # Reversed: ["elderberry", "date", "cherry", "banana", "apple"]

Modifying Lists

items = [1, 2, 3]

# Add elements
items.append(4)          # [1, 2, 3, 4] — add to end
items.insert(1, 99)      # [1, 99, 2, 3, 4] — insert at index 1
items.extend([5, 6, 7])  # [1, 99, 2, 3, 4, 5, 6, 7] — add multiple

# Remove elements
items.remove(99)         # Removes first occurrence of 99
popped = items.pop()     # Removes and returns last element
popped2 = items.pop(0)   # Removes and returns element at index 0
del items[2]             # Removes element at index 2

# Modify in place
items[0] = 100           # Replace element
items[1:3] = [200, 300]  # Replace a slice

Essential List Methods

numbers = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]

# Information
print(len(numbers))              # 11
print(numbers.count(5))          # 3 — how many times 5 appears
print(numbers.index(9))          # 5 — index of first occurrence

# Searching
print(4 in numbers)              # True
print(7 in numbers)              # False

# Ordering
numbers.sort()                           # Sort in-place: [1, 1, 2, 3, 3, 4, 5, 5, 5, 6, 9]
numbers.sort(reverse=True)               # Descending
sorted_copy = sorted(numbers)            # Returns new sorted list (original unchanged)
numbers.reverse()                        # Reverse in-place

# Sorting with a key
words = ["banana", "apple", "cherry", "date"]
words.sort(key=len)                      # Sort by length
words.sort(key=str.lower)               # Case-insensitive sort

List Operations

a = [1, 2, 3]
b = [4, 5, 6]

# Concatenation
combined = a + b          # [1, 2, 3, 4, 5, 6]

# Repetition
repeated = [0] * 5        # [0, 0, 0, 0, 0]

# Copy a list (important — assignment doesn't copy!)
original = [1, 2, 3]
alias = original          # NOT a copy — both point to same list!
copy1 = original.copy()   # Shallow copy
copy2 = original[:]       # Also a shallow copy
copy3 = list(original)    # Also a shallow copy

# Demonstrate aliasing trap
alias.append(99)
print(original)   # [1, 2, 3, 99] — original was modified!
copy1.append(99)
print(original)   # [1, 2, 3, 99] — copy1 is independent

The Most Useful List Techniques

# Unpack a list into variables
first, *rest = [1, 2, 3, 4, 5]
print(first)   # 1
print(rest)    # [2, 3, 4, 5]

first, *middle, last = [1, 2, 3, 4, 5]
print(first, middle, last)   # 1 [2, 3, 4] 5

# Flatten a nested list
nested = [[1, 2], [3, 4], [5, 6]]
flat = [x for sublist in nested for x in sublist]
print(flat)   # [1, 2, 3, 4, 5, 6]

# Remove duplicates while preserving order
seen = set()
unique = [x for x in numbers if not (x in seen or seen.add(x))]

# Zip two lists and create a dict
keys = ["a", "b", "c"]
values = [1, 2, 3]
d = dict(zip(keys, values))   # {'a': 1, 'b': 2, 'c': 3}

# Find the index of the maximum value
scores = [45, 92, 78, 55, 88]
best_idx = scores.index(max(scores))   # 1 — index of 92

Sorting with Complex Keys

students = [
    {"name": "Alice", "grade": 92, "age": 20},
    {"name": "Bob",   "grade": 78, "age": 22},
    {"name": "Carol", "grade": 92, "age": 19},
]

# Sort by grade, then by name alphabetically
students.sort(key=lambda s: (-s['grade'], s['name']))

for s in students:
    print(f"{s['name']}: {s['grade']}")
# Alice: 92
# Carol: 92
# Bob: 78

Common Mistakes and How to Avoid Them

# Mistake 1: Modifying a list while iterating over it
items = [1, 2, 3, 4, 5]
for item in items:
    if item % 2 == 0:
        items.remove(item)   # BUG: skips elements
# Fix: iterate over a copy
for item in items[:]:
    if item % 2 == 0:
        items.remove(item)   # Safe

# Mistake 2: Mutable default argument
def add_item(item, lst=[]):   # BUG: lst is shared across all calls!
    lst.append(item)
    return lst
# Fix:
def add_item(item, lst=None):
    if lst is None:
        lst = []
    lst.append(item)
    return lst

# Mistake 3: Using + to append in a loop (slow)
result = []
for i in range(10000):
    result = result + [i]   # Creates new list each time — O(n²)
# Fix:
result = []
for i in range(10000):
    result.append(i)        # O(1) amortized — much faster

Next lesson: Dictionaries — Python's key-value powerhouse for structured data.

📱

Get this course's notes on Telegram!

Free cheat sheets, summaries & practice exercises

Get Notes Free →
!