Data StructuresPython Lists
A list is an ordered, mutable collection of items. It is one of Python's most versatile and frequently used data structures. A list can hold any mix of data types — integers, strings, floats, booleans, even other lists — all in one place.
Ordered means the items have a defined sequence and that sequence is preserved. Mutable means you can change, add, and remove items after the list has been created. This makes lists the go-to structure whenever you need a collection that changes over time.
Creating a List
Lists are created using square brackets, with items separated by commas. An empty list is created with just [].
fruits = ["apple", "banana", "cherry"]
numbers = [1, 2, 3, 4, 5]
mixed = ["Alice", 30, True, 3.14]
empty = []
print(fruits)
print(mixed)
print(len(fruits)) # Number of items
Output['apple', 'banana', 'cherry']
['Alice', 30, True, 3.14]
3
Accessing Items
Access individual items using their index inside square brackets. Python lists use zero-based indexing — the first item is at index 0.
fruits = ["apple", "banana", "cherry", "date"]
print(fruits[0]) # First item
print(fruits[1]) # Second item
print(fruits[3]) # Fourth item
Outputapple
banana
date
Negative Indexing
Negative indexing counts from the end of the list. Index -1 is always the last item, -2 is second-to-last, and so on. This is extremely useful when you want the last item without knowing the list's length.
fruits = ["apple", "banana", "cherry", "date"]
print(fruits[-1]) # Last item
print(fruits[-2]) # Second to last
print(fruits[-4]) # First item (same as index 0)
Outputdate
cherry
apple
Slicing a List
Slicing extracts a sub-section of a list. The syntax is list[start:end] — the item at start is included, the item at end is excluded. Omitting start defaults to the beginning; omitting end defaults to the end.
numbers = [10, 20, 30, 40, 50, 60, 70]
print(numbers[1:4]) # Index 1, 2, 3
print(numbers[:3]) # From start to index 2
print(numbers[4:]) # From index 4 to end
print(numbers[-3:]) # Last 3 items
print(numbers[::2]) # Every second item (step of 2)
Output[20, 30, 40]
[10, 20, 30]
[50, 60, 70]
[50, 60, 70]
[10, 30, 50, 70]
Changing an Item
Because lists are mutable, you can change the value at any index by assigning a new value directly to that position.
fruits = ["apple", "banana", "cherry"]
fruits[1] = "blueberry" # Replace banana
print(fruits)
fruits[-1] = "mango" # Replace last item
print(fruits)
Output['apple', 'blueberry', 'cherry']
['apple', 'blueberry', 'mango']
Appending Items
The .append() method adds a single item to the end of the list. This is the most common way to build up a list dynamically.
cart = ["laptop", "mouse"]
cart.append("keyboard")
cart.append("monitor")
print(cart)
print(len(cart))
Output['laptop', 'mouse', 'keyboard', 'monitor']
4
Inserting Items
The .insert(index, value) method adds an item at a specific position, shifting all items to the right of that position up by one index.
fruits = ["apple", "cherry", "date"]
fruits.insert(1, "banana") # Insert at index 1
print(fruits)
fruits.insert(0, "avocado") # Insert at the very beginning
print(fruits)
Output['apple', 'banana', 'cherry', 'date']
['avocado', 'apple', 'banana', 'cherry', 'date']
Removing Items
Python gives you multiple ways to remove items from a list, each suited to a different situation. Choose the right tool for the job.
fruits = ["apple", "banana", "cherry", "banana"]
# .remove() — removes the FIRST occurrence of a value
fruits.remove("banana")
print(fruits) # Second banana still there
# .pop() — removes and RETURNS item at index (default: last item)
removed = fruits.pop()
print(removed)
print(fruits)
# del — removes item at specific index, returns nothing
del fruits[0]
print(fruits)
Output['apple', 'cherry', 'banana']
banana
['apple', 'cherry']
['cherry']
- .remove(value) — searches by value, removes first match, raises ValueError if not found
- .pop(index) — removes by index, returns the removed value, last item if index omitted
- del list[index] — removes by index, returns nothing, can also delete slices
Clearing a List
The .clear() method removes all items from a list, leaving an empty list. The list object itself still exists — it is just empty.
session_log = ["login", "view_dashboard", "edit_profile", "logout"]
print(len(session_log))
session_log.clear()
print(session_log)
print(len(session_log))
Output4
[]
0
Looping Through a List
The for loop is the standard way to iterate through every item in a list. Each iteration, the loop variable takes the value of the next item.
languages = ["Python", "JavaScript", "Go", "Rust"]
for language in languages:
print(f"I love {language}!")
# Loop with index using enumerate()
for index, language in enumerate(languages):
print(f"{index}: {language}")
OutputI love Python!
I love JavaScript!
I love Go!
I love Rust!
0: Python
1: JavaScript
2: Go
3: Rust
List Comprehension
List comprehension is Python's elegant one-liner syntax for creating a new list by applying an expression to each item in an existing sequence. It replaces multiple lines of loop code with a single expressive line.
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# Classic loop approach
squares_loop = []
for n in numbers:
squares_loop.append(n ** 2)
# List comprehension — same result, one line
squares = [n ** 2 for n in numbers]
print(squares)
# With a filter condition
evens = [n for n in numbers if n % 2 == 0]
print(evens)
# Transform and filter together
big_squares = [n ** 2 for n in numbers if n > 5]
print(big_squares)
Output[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
[2, 4, 6, 8, 10]
[36, 49, 64, 81, 100]
Sorting a List
Python provides two ways to sort a list. .sort() sorts the list in place (modifies the original). sorted() returns a new sorted list and leaves the original unchanged.
scores = [88, 45, 73, 92, 61]
# sorted() — does not modify original
ranked = sorted(scores)
print(ranked)
print(scores) # original unchanged
# .sort() — modifies in place
scores.sort()
print(scores)
# Reverse sort
scores.sort(reverse=True)
print(scores)
Output[45, 61, 73, 88, 92]
[88, 45, 73, 92, 61]
[45, 61, 73, 88, 92]
[92, 88, 73, 61, 45]
Copying a List
Copying a list in Python has a critical trap that catches most beginners. When you write b = a, you are NOT creating a copy — you are creating a second name that points to the same list in memory. Changes through b will also affect a.
original = [1, 2, 3]
# WRONG — this is not a copy, it is an alias
alias = original
alias.append(99)
print(original) # original is affected!
# CORRECT — use .copy() or list() to make a true copy
original2 = [1, 2, 3]
true_copy = original2.copy()
true_copy.append(99)
print(original2) # original2 is unchanged
print(true_copy)
Output[1, 2, 3, 99]
[1, 2, 3]
[1, 2, 3, 99]
💡Critical Rule: Never use b = a to copy a list. Use b = a.copy(), b = list(a), or b = a[:] (slice copy). This is one of the most common sources of hard-to-find bugs in Python.
Joining Lists
You can combine two or more lists using the + operator (creates a new list) or .extend() (adds items from another list to an existing one in place).
backend = ["Python", "Django", "PostgreSQL"]
frontend = ["HTML", "CSS", "JavaScript"]
# + creates a new combined list
full_stack = backend + frontend
print(full_stack)
# .extend() adds to an existing list in place
backend.extend(frontend)
print(backend)
Output['Python', 'Django', 'PostgreSQL', 'HTML', 'CSS', 'JavaScript']
['Python', 'Django', 'PostgreSQL', 'HTML', 'CSS', 'JavaScript']