Lists in Python

A list (type list) is an ordered, mutable collection of elements. In this article we'll cover how to create lists, access their elements, modify them, and what methods they have.

What is a list?

A list in Python is an ordered, mutable collection of elements that can be of different types. You can think of a list as a container that stores various objects arranged in a specific order.

The main properties of lists:

  • Ordered: elements are stored in the order they were added
  • Mutable: you can add, remove, and change elements after creating the list
  • Indexable: each element can be accessed by its position (index)
  • Allow duplicates: the same element can appear in the list multiple times

Creating lists

There are several ways to create lists in Python:

Using square brackets []

Python 3.13
# Empty list
empty_list = []
print(empty_list)
[]
# List of numbers
numbers = [1, 2, 3, 4, 5]
print(numbers)
[1, 2, 3, 4, 5]
# List of different data types
mixed = [1, "hello", True, 3.14]
print(mixed)
[1, 'hello', True, 3.14]
# Nested lists (list of lists)
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
print(matrix)
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]

Using the list() constructor

Python 3.13
# Creating an empty list
empty_list = list()
print(empty_list)
[]
# Creating a list from a string (each character becomes an element)
chars = list("Python")
print(chars)
['P', 'y', 't', 'h', 'o', 'n']
# Creating a list from other iterable objects
tuple_to_list = list((1, 2, 3))
print(tuple_to_list)
[1, 2, 3]
set_to_list = list({1, 2, 3})
print(set_to_list)
[1, 2, 3]

Accessing list elements

Indexing

In Python, indexing starts at 0, meaning the first element has index 0, the second one has index 1, and so on:

Python 3.13
fruits = ["apple", "banana", "cherry", "pear", "orange"]

# Getting elements by index
first_fruit = fruits[0]
print(f"First fruit: {first_fruit}")
First fruit: apple
# Negative indices for accessing from the end of the list
last_fruit = fruits[-1]
print(f"Last fruit: {last_fruit}")
Last fruit: orange
second_last = fruits[-2]
print(f"Second to last fruit: {second_last}")
Second to last fruit: pear

Slices

Slices allow you to get a sublist by specifying start and end indices:

Python 3.13
fruits = ["apple", "banana", "cherry", "pear", "orange"]

# Slice syntax: list[start:end:step]
# Start is included, end is not included!

# First three elements
first_three = fruits[0:3]
print(f"First three fruits: {first_three}")
First three fruits: ['apple', 'banana', 'cherry']
# Same thing, but the starting index can be omitted if it's 0
first_three = fruits[:3]
print(f"First three fruits: {first_three}")
First three fruits: ['apple', 'banana', 'cherry']
# Every second element
every_second = fruits[::2]
print(f"Every second fruit: {every_second}")
Every second fruit: ['apple', 'cherry', 'orange']
# Reversing the list
reversed_list = fruits[::-1]
print(f"List in reverse order: {reversed_list}")
List in reverse order: ['orange', 'pear', 'cherry', 'banana', 'apple']

Modifying list elements

The key difference from strings: lists are mutable. A string can't be changed in place — you have to build a new one (recall the strings lesson). But list elements can be changed, added, and removed inside the existing object:

Python 3.13
fruits = ["apple", "banana", "cherry"]

# Changing an element
fruits[0] = "kiwi"
print(fruits)
['kiwi', 'banana', 'cherry']
# Changing multiple elements using a slice
numbers = [1, 2, 3, 4, 5]
numbers[1:4] = [20, 30, 40]
print(numbers)
[1, 20, 30, 40, 5]
# You can even replace multiple elements with a different number of elements
numbers = [1, 2, 3, 4, 5]
numbers[1:4] = [20, 30]
print(numbers)
[1, 20, 30, 5]

Main list methods

Python provides many built-in methods for working with lists:

Adding elements

Python 3.13
fruits = ["apple", "banana"]

# Adding an element to the end of the list
fruits.append("cherry")
print(fruits)
['apple', 'banana', 'cherry']
# Inserting an element at a specific position
fruits.insert(1, "orange")
print(fruits)
['apple', 'orange', 'banana', 'cherry']
# Adding elements from another list
more_fruits = ["pear", "grape"]
fruits.extend(more_fruits)
print(fruits)
['apple', 'orange', 'banana', 'cherry', 'pear', 'grape']
# Combining lists using the + operator
combined = fruits + ["pineapple", "mango"]
print(combined)
['apple', 'orange', 'banana', 'cherry', 'pear', 'grape', 'pineapple', 'mango']

Removing elements

Python 3.13
fruits = ["apple", "banana", "cherry", "orange", "banana"]

# Removing an element by value (removes only the first occurrence)
fruits.remove("banana")
print(fruits)
['apple', 'cherry', 'orange', 'banana']
# Removing an element by index and returning its value
removed = fruits.pop(1)
print(f"Removed: {removed}")
Removed: cherry
print(f"List after removal: {fruits}")
List after removal: ['apple', 'orange', 'banana']
# If no index is specified, pop() removes and returns the last element
last = fruits.pop()
print(f"Last element: {last}")
Last element: banana
print(fruits)
['apple', 'orange']
# Removing all elements from the list
fruits.clear()
print(f"Empty list: {fruits}")
Empty list: []
# The del operator for removing elements by index or slice
numbers = [1, 2, 3, 4, 5]
del numbers[0]
print(numbers)
[2, 3, 4, 5]
del numbers[1:3]
print(numbers)
[2, 5]

Finding and counting elements

Python 3.13
fruits = ["apple", "banana", "cherry", "banana", "pear"]

# Checking if an element is in the list
print("banana" in fruits)
True
print("watermelon" in fruits)
False
# Finding the index of the first occurrence of an element
banana_index = fruits.index("banana")
print(f"Index of the first banana: {banana_index}")
Index of the first banana: 1
# Counting the number of occurrences of an element
banana_count = fruits.count("banana")
print(f"Number of bananas: {banana_count}")
Number of bananas: 2

Sorting and reversing

Python 3.13
# Sorting a list (modifies the original list)
numbers = [3, 1, 4, 1, 5, 9, 2]
numbers.sort()
print(f"Sorted list: {numbers}")
Sorted list: [1, 1, 2, 3, 4, 5, 9]
# Sorting in reverse order
numbers.sort(reverse=True)
print(f"Reverse sort: {numbers}")
Reverse sort: [9, 5, 4, 3, 2, 1, 1]
# If you don't want to modify the original list, use sorted()
original = [3, 1, 4, 1, 5]
sorted_list = sorted(original)
print(f"Original: {original}")
Original: [3, 1, 4, 1, 5]
print(f"Sorted copy: {sorted_list}")
Sorted copy: [1, 1, 3, 4, 5]

Copying lists

This is one of the most common sources of bugs for beginners: assigning a list does not create a copy. Both variables point to the same object in memory. If you change the list through one variable, the other will see the change.

Assignment vs copying: with reference = original both variables point to the same box, while copy = original.copy() creates a new box

Python 3.13
# Create a list
original = [1, 2, 3]

# Assignment doesn't create a copy — both variables point to the same list
reference = original
reference.append(4)
print(f"Original after changing the reference: {original}")
Original after changing the reference: [1, 2, 3, 4]
# Correct ways to copy a list:
# 1. The copy() method
copy1 = original.copy()

# 2. Using slice [:]
copy2 = original[:]

# 3. The list() function
copy3 = list(original)

# Let's check that the copies are not linked to the original
copy1.append(5)
print(f"Original: {original}")
Original: [1, 2, 3, 4]
print(f"Copy 1: {copy1}")
Copy 1: [1, 2, 3, 4, 5]

Practical example of using a list

Python 3.13
# List of students and their grades
students = ["Anna", "John", "Maria", "Peter", "Elena"]
grades = [95, 82, 90, 78, 88]

# Finding the student with the highest score
highest_score = max(grades)
top_student_index = grades.index(highest_score)
print(f"Best student: {students[top_student_index]} with a grade of {highest_score}")
Best student: Anna with a grade of 95

Understanding check

Which of the following methods will correctly create a copy of a list that is not linked to the original?