Working with Text and Collections

Lists and List Operations

7 min read

When you need to store more than one thing

So far, every variable has held a single value: one name, one age, one price. But real programs almost always deal with collections of things:

  • A shopping list with many items
  • A class roster with many student names
  • A series of daily temperatures
  • A set of scores from a game

Python's list is the go-to data structure for ordered collections. A list can hold as many items as you need, and those items can be any type — strings, numbers, or even a mix.


Creating a list

A list is written with square brackets [], with each item separated by a comma:

shopping_list = ["milk", "eggs", "bread", "apples"]
print(shopping_list)
# ['milk', 'eggs', 'bread', 'apples']

An empty list:

my_list = []

A list of numbers:

scores = [85, 92, 78, 95, 60]

A list with mixed types (this is valid Python, though unusual in practice):

mixed = ["Alice", 30, True, 9.99]

Accessing items by index

Lists are ordered — the items stay in the order you put them, and each has an index starting at 0, just like strings.

shopping_list = ["milk", "eggs", "bread", "apples"]

print("First item:", shopping_list[0])   # milk
print("Second item:", shopping_list[1])  # eggs
print("Last item:", shopping_list[-1])   # apples

Negative indexes count from the end: -1 is the last item, -2 is second-to-last.

Diagram showing a list ["milk", "eggs", "bread", "apples"] with index numbers 0-3 above and negative indexes -4 to -1 below each item


Checking the length

len() is a built-in function that returns the number of items in a list:

shopping_list = ["milk", "eggs", "bread", "apples"]
print("Total items:", len(shopping_list))  # Total items: 4

Adding items

.append() — add to the end

shopping_list = ["milk", "eggs", "bread", "apples"]
shopping_list.append("cheese")
print("Updated list:", shopping_list)
# ['milk', 'eggs', 'bread', 'apples', 'cheese']

.insert() — add at a specific position

my_list = [1, 2, 3, 4, 5]
my_list.insert(2, 2.5)  # Insert 2.5 at index 2
print(my_list)
# [1, 2, 2.5, 3, 4, 5]

.insert(index, value) shifts existing items to the right to make room.


Removing items

.remove() — remove by value

fruits = ["apple", "banana", "cherry", "apple"]
fruits.remove("banana")
print(fruits)
# ['apple', 'cherry', 'apple']

Removes the first occurrence of the value.

.pop() — remove by index (or last item)

my_list = [1, 2, 2.5, 4, 5, 6]
last_item = my_list.pop()   # removes and returns the last item
print(last_item)  # 6
print(my_list)    # [1, 2, 2.5, 4, 5]

.pop() without an argument removes the last item. .pop(index) removes the item at that index.

del — remove by index without returning it

colors = ["red", "blue", "green", "orange"]
del colors[1]
print(colors)
# ['red', 'green', 'orange']

del list[index] deletes the item at that position. Unlike .pop(), it doesn't give the value back — use it when you just want the item gone.

Watch out: calling .remove() with a value that isn't in the list raises a ValueError:

colors.remove("yellow")
# ValueError: list.remove(x): x not in list

Sorting and searching

.sort() — sort the list in place

fruits = ["apple", "blueberry", "cherry", "apple", "date"]
fruits.sort()
print(fruits)
# ['apple', 'apple', 'blueberry', 'cherry', 'date']

Numbers sort numerically; strings sort alphabetically. "In place" means .sort() rearranges the original list rather than returning a new one.

.reverse() — reverse the list in place

colors = ["red", "orange", "green"]
colors.reverse()
print(colors)
# ['green', 'orange', 'red']

Just like .sort(), .reverse() modifies the original list rather than returning a new one.

.index() — find the position of an item

fruits = ["apple", "blueberry", "cherry"]
print(fruits.index("cherry"))  # 2

.count() — count how many times a value appears

fruits = ["apple", "blueberry", "cherry", "apple", "date"]
print(fruits.count("apple"))  # 2

List slicing

Just like strings, lists support slicing using [start:end]:

numbers = [2, 4, 6, 8, 10]
print("First three:", numbers[:3])         # [2, 4, 6]
print("Last two:", numbers[-2:])           # [8, 10]
print("Every other item:", numbers[::2])   # [2, 6, 10]

The ::2 step syntax means "take every 2nd item."


Looping through a list

A for loop is the standard way to process every item in a list — you'll learn all about loops in a dedicated lesson, but here's a preview:

numbers = [2, 4, 6, 8, 10]
for number in numbers:
    print("Number:", number)

Output:

Number: 2
Number: 4
Number: 6
Number: 8
Number: 10

Using a list as a stack

A stack is a collection where you only ever add or remove from one end — the last item in is the first item out. Python lists already support this with two methods you've just learned:

  • .append(item)push a new item onto the top
  • .pop()pop the top item back off
stack = [10, 20, 30, 40]
stack.append(50)     # push
print(stack)          # [10, 20, 30, 40, 50]

top = stack.pop()     # pop
print(top)            # 50
print(stack)          # [10, 20, 30, 40]

No new syntax here — it's the same .append() and .pop() you already know, just used in a specific pattern. Stacks show up naturally whenever you need to undo actions, track function calls, or process items in reverse order of arrival.


Practice: sorting numbers into even and odd

A common pattern: loop through a range of numbers and sort each one into the right list based on a condition.

even = []
odd = []

for num in range(1, 51):
    if num % 2 == 0:
        even.append(num)
    else:
        odd.append(num)

print("Evens:", even)
print("Odds:", odd)

Each number from 1 to 50 gets tested with num % 2 == 0 and appended to whichever list matches.


A complete example

Here's a practical example that builds a fruit list, modifies it with several methods, and inspects the result:

fruits = ["apple", "banana", "cherry", "apple"]
print("Original list:", fruits)

fruits.append("date")
print("After append:", fruits)

fruits.insert(1, "blueberry")
print("After insert:", fruits)

fruits.remove("banana")
print("After remove:", fruits)

print("Index of cherry:", fruits.index("cherry"))

fruits.sort()
print("Sorted list:", fruits)

print("Count of apple:", fruits.count("apple"))

Output:

Original list: ['apple', 'banana', 'cherry', 'apple']
After append: ['apple', 'banana', 'cherry', 'apple', 'date']
After insert: ['apple', 'blueberry', 'banana', 'cherry', 'apple', 'date']
After remove: ['apple', 'blueberry', 'cherry', 'apple', 'date']
Index of cherry: 2
Sorted list: ['apple', 'apple', 'blueberry', 'cherry', 'date']
Count of apple: 2

Quick reference: common list methods

MethodWhat it does
.append(item)Adds item to the end
.insert(i, item)Inserts item at position i
.remove(item)Removes first occurrence of item
.pop()Removes and returns the last item
.pop(i)Removes and returns item at index i
del list[i]Removes the item at index i (no return value)
.sort()Sorts the list in place
.reverse()Reverses the list in place
.index(item)Returns the index of item
.count(item)Counts occurrences of item
len(list)Returns the number of items

Key takeaway

A Python list stores an ordered collection of items in square brackets. You access items by index (starting at 0), add and remove items with methods like .append(), .insert(), .remove(), and .pop(), and inspect the list with .sort(), .index(), and len(). Lists are one of the most-used data structures in all of Python.

What's next?

Lists can hold any type of item — including other lists. Next, you'll see how nested lists let you represent tables, grids, and grouped records, all using the tools you just learned.