Learn Without Walls
← Lesson 2 Lesson 3 of 4 Lesson 4 →

Lesson 6.3: Slicing and Indexing

By the end of this lesson, you will be able to:

What is Slicing?

Slicing: Slicing extracts a portion (sublist) from a list using the syntax list[start:stop:step]. The result is a new list containing the selected elements.

While indexing gives you a single element, slicing gives you a range of elements. Think of it like cutting a section from a loaf of bread -- you specify where to start cutting and where to stop.

Basic Slice Syntax

numbers = [10, 20, 30, 40, 50, 60, 70]
#           0    1    2    3    4    5    6

# Get elements from index 1 to 4 (not including 4)
subset = numbers[1:4]
print(subset)

# Get elements from index 2 to 6
print(numbers[2:6])
[20, 30, 40] [30, 40, 50, 60]

Key Rule: Stop Index is Exclusive

The slice [start:stop] includes the element at start but does NOT include the element at stop. This is the same as how range() works.

Omitting Start, Stop, or Step

You can omit any of the three values, and Python will use defaults:

numbers = [10, 20, 30, 40, 50, 60, 70]

# From beginning to index 3
print(numbers[:3])

# From index 4 to the end
print(numbers[4:])

# Get the entire list (copy)
print(numbers[:])

# First three elements
print(numbers[:3])

# Last three elements
print(numbers[-3:])
[10, 20, 30] [50, 60, 70] [10, 20, 30, 40, 50, 60, 70] [10, 20, 30] [50, 60, 70]

Using the Step Parameter

The third value in the slice specifies the step -- how many elements to skip between each selected element.

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

# Every other element
print(numbers[::2])

# Every third element
print(numbers[::3])

# Every other element from index 1 to 8
print(numbers[1:8:2])
[0, 2, 4, 6, 8] [0, 3, 6, 9] [1, 3, 5, 7]

Practical Example: Extracting Even and Odd Positioned Items

students = ["Alice", "Bob", "Charlie", "Diana", "Eve", "Frank"]

# Students at even indexes (0, 2, 4)
team_a = students[::2]
print("Team A:", team_a)

# Students at odd indexes (1, 3, 5)
team_b = students[1::2]
print("Team B:", team_b)
Team A: ['Alice', 'Charlie', 'Eve'] Team B: ['Bob', 'Diana', 'Frank']

Reversing with Slicing

Using a step of -1 reverses the list. This creates a new reversed list without modifying the original.

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

# Reverse the list
reversed_nums = numbers[::-1]
print("Reversed:", reversed_nums)
print("Original:", numbers)   # Original unchanged
Reversed: [5, 4, 3, 2, 1] Original: [1, 2, 3, 4, 5]

Negative Step with Start and Stop

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

# From index 7 down to index 2 (not including 2)
print(numbers[7:2:-1])

# Every other element in reverse
print(numbers[::-2])
[7, 6, 5, 4, 3] [9, 7, 5, 3, 1]

Copying Lists Safely

Important: In Python, assigning a list to a new variable does NOT create a copy. Both variables point to the same list in memory. Use slicing or .copy() to make a true copy.
# This does NOT copy the list!
original = [1, 2, 3]
not_a_copy = original    # Both point to same list
not_a_copy.append(4)
print("Original:", original)    # Original is also changed!
print("Not a copy:", not_a_copy)
Original: [1, 2, 3, 4] Not a copy: [1, 2, 3, 4]
# Use slicing to create a true copy
original = [1, 2, 3]
copy1 = original[:]       # Slice copy
copy2 = original.copy()   # .copy() method

copy1.append(99)
print("Original:", original)     # Unchanged!
print("Copy 1:", copy1)
print("Copy 2:", copy2)
Original: [1, 2, 3] Copy 1: [1, 2, 3, 99] Copy 2: [1, 2, 3]

Try It Yourself

Create a list data = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]. Using slicing, extract: (1) the first five elements, (2) the last three elements, (3) every third element, and (4) the list in reverse.

Slicing with Negative Indexes

You can mix positive and negative indexes in slices for flexible data extraction.

letters = ["a", "b", "c", "d", "e", "f", "g"]

# Everything except the first and last
print(letters[1:-1])

# Last four elements
print(letters[-4:])

# Everything except the last two
print(letters[:-2])
['b', 'c', 'd', 'e', 'f'] ['d', 'e', 'f', 'g'] ['a', 'b', 'c', 'd', 'e']

Slicing Never Causes IndexError

Unlike individual indexing, slicing gracefully handles out-of-range values. It simply returns what is available.

short = [1, 2, 3]
print(short[0:100])   # No error, returns all elements
print(short[10:20])   # No error, returns empty list
[1, 2, 3] []

Check Your Understanding

Given: data = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

  1. What does data[2:5] return?
  2. What does data[::3] return?
  3. What does data[::-1] return?
  4. How do you copy a list using slicing?
  1. [2, 3, 4] (from index 2 up to but not including 5)
  2. [0, 3, 6, 9] (every third element)
  3. [9, 8, 7, 6, 5, 4, 3, 2, 1, 0] (reversed)
  4. copy = data[:] (slice with no start or stop)

Key Takeaways