How does slicing work in Python?

Here’s a detailed breakdown of Python slicing, including mechanics, edge cases, and advanced examples:

1. Slicing Syntax

sequence[start : stop : step]
  • All parameters are optional: start (default 0), stop (default len(sequence)), and step (default 1).
  • Returns a new sequence (original remains unmodified).
  • Works with lists, strings, tuples, bytes, and NumPy arrays.

2. Parameter Behavior

ParameterDescription
startInclusive starting index (use None to default to 0).
stopExclusive ending index (use None to default to end of sequence).
stepInterval between elements. If negative, iterates backward.

3. Key Concepts

A. Negative Indices

  • -1 = last element, -2 = second last, etc.
  my_list = [0, 1, 2, 3, 4]
  print(my_list[-3:])   # Last 3 elements → [2, 3, 4]

B. Negative Step

  • When step < 0, the slice starts from start and moves backward.
  my_list = [0, 1, 2, 3, 4]
  print(my_list[3:0:-1])  # From index 3 to 1 (exclusive) → [3, 2, 1]

C. Out-of-Bounds Handling

  • Python silently adjusts out-of-range indices:
  my_list = [0, 1, 2]
  print(my_list[0:10])  # → [0, 1, 2]

4. Detailed Examples

Example 1: Basic Slicing

text = "abcdefgh"
print(text[2:5])      # "cde" (indices 2, 3, 4)
print(text[:4])       # "abcd" (start=0, stop=4)
print(text[3:])       # "defgh" (start=3 to end)

Example 2: Step Size

nums = [0, 1, 2, 3, 4, 5, 6]
print(nums[::2])      # [0, 2, 4, 6] (every 2nd element)
print(nums[1::3])     # [1, 4] (start=1, step=3)
print(nums[::-1])     # [6, 5, 4, 3, 2, 1, 0] (reverse)

Example 3: Negative Indices + Step

data = [10, 20, 30, 40, 50]
print(data[-2::-1])   # From index -2 (40) backward: [40, 30, 20, 10]
print(data[-1:2:-1])  # From -1 (50) to index 3 (exclusive): [50, 40]

Example 4: Modifying Lists with Slices

my_list = [0, 1, 2, 3, 4]
my_list[1:3] = [10, 20]   # Replace indices 1-2 → [0, 10, 20, 3, 4]
my_list[::2] = [5, 15, 25]  # Assign to even indices → [5, 10, 15, 3, 25]
del my_list[2:4]          # Delete elements 2-3 → [5, 10, 25]

Example 5: Strings and Tuples

s = "hello"
print(s[1:4:2])    # "el" → indices 1 ('e') and 3 ('l')

t = (0, 1, 2, 3)
print(t[-2:])      # (2, 3)

5. Advanced Use Cases

A. Slice Objects

Create reusable slices:

even_slice = slice(None, None, 2)  # Equivalent to [::2]
print(my_list[even_slice])          # Get even-indexed elements

B. Multi-Dimensional Slicing (e.g., NumPy)

import numpy as np
arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print(arr[:, 1])     # Get second column → [2, 5, 8]

C. Edge Cases

empty_list = []
print(empty_list[:3])    # → [] (no error)

my_str = "abc"
print(my_str[5:])        # → "" (empty string)

6. Key Takeaways

  • Slicing does not mutate the original sequence.
  • sequence[::-1] is a common idiom to reverse sequences.
  • Use del sequence[a:b] to delete a slice.
  • Slices handle out-of-bounds indices gracefully.

7. Common Pitfalls

  • Reversing with step=-1:
  # To reverse the entire list:
  my_list = [1, 2, 3]
  reversed_list = my_list[::-1]  # Correct → [3, 2, 1]
  partial_reverse = my_list[2:0:-1]  # → [3, 2] (stops before index 0)
  • Empty slices when start >= stop (with positive step):
  print(my_list[3:1])  # → []

Let me know if you’d like to explore a specific scenario!

Leave a Reply

Your email address will not be published. Required fields are marked *