- 5.1 Introduction
- 5.2 Lists
- 5.3 Tuples
- 5.4 Unpacking Sequences
- 5.5 Sequence Slicing
- 5.6 del Statement
- 5.7 Passing Lists to Functions
- 5.8 Sorting Lists
- 5.9 Searching Sequences
- 5.10 Other List Methods
- 5.11 Simulating Stacks with Lists
- 5.12 List Comprehensions
- 5.13 Generator Expressions
- 5.14 Filter, Map and Reduce
- 5.15 Other Sequence Processing Functions
- 5.16 Two-Dimensional Lists
- 5.17 Intro to Data Science: Simulation and Static Visualizations
- 5.18 Wrap-Up

## 5.5 Sequence Slicing

You can **slice** sequences to create new sequences of the same type containing *subsets* of the original elements. Slice operations can modify mutable sequences—those that do *not* modify a sequence work identically for lists, tuples and strings.

#### Specifying a Slice with Starting and Ending Indices

Let’s create a slice consisting of the elements at indices 2 through 5 of a list:

In [1]: numbers = [2, 3, 5, 7, 11, 13, 17, 19] In [2]: numbers[2:6] Out[2]: [5, 7, 11, 13]

The slice *copies* elements from the *starting index* to the left of the colon (`2`) up to, but not including, the *ending index* to the right of the colon (`6`). The original list is not modified.

#### Specifying a Slice with Only an Ending Index

If you omit the starting index, `0` is assumed. So, the slice `numbers[:6]` is equivalent to the slice `numbers[0:6]`:

In [3]: numbers[:6] Out[3]: [2, 3, 5, 7, 11, 13] In [4]: numbers[0:6] Out[4]: [2, 3, 5, 7, 11, 13]

#### Specifying a Slice with Only a Starting Index

If you omit the ending index, Python assumes the sequence’s length (`8` here), so snippet `[5]`’s slice contains the elements of `numbers` at indices `6` and `7`:

In [5]: numbers[6:] Out[5]: [17, 19] In [6]: numbers[6:len(numbers)] Out[6]: [17, 19]

#### Specifying a Slice with No Indices

Omitting both the start and end indices copies the entire sequence:

In [7]: numbers[:] Out[7]: [2, 3, 5, 7, 11, 13, 17, 19]

Though slices create new objects, slices make **shallow copies** of the elements—that is, they copy the elements’ references but not the objects they point to. So, in the snippet above, the new list’s elements refer to the *same objects* as the original list’s elements, rather than to separate copies. In the “Array-Oriented Programming with NumPy” chapter, we’ll explain *deep* copying, which actually copies the referenced objects themselves, and we’ll point out when deep copying is preferred.

#### Slicing with Steps

The following code uses a *step* of `2` to create a slice with every other element of `numbers`:

In [8]: numbers[::2] Out[8]: [2, 5, 11, 17]

We omitted the start and end indices, so `0` and `len(numbers)` are assumed, respectively.

#### Slicing with Negative Indices and Steps

You can use a negative step to select slices in *reverse* order. The following code concisely creates a new list in reverse order:

In [9]: numbers[::-1] Out[9]: [19, 17, 13, 11, 7, 5, 3, 2]

This is equivalent to:

In [10]: numbers[-1:-9:-1] Out[10]: [19, 17, 13, 11, 7, 5, 3, 2]

#### Modifying Lists Via Slices

You can modify a list by assigning to a slice of it—the rest of the list is unchanged. The following code replaces `numbers`’ first three elements, leaving the rest unchanged:

In [11]: numbers[0:3] = ['two', 'three', 'five'] In [12]: numbers Out[12]: ['two', 'three', 'five', 7, 11, 13, 17, 19]

The following deletes only the first three elements of `numbers` by assigning an *empty* list to the three-element slice:

In [13]: numbers[0:3] = [] In [14]: numbers Out[14]: [7, 11, 13, 17, 19]

The following assigns a list’s elements to a slice of every other element of `numbers`:

In [15]: numbers = [2, 3, 5, 7, 11, 13, 17, 19] In [16]: numbers[::2] = [100, 100, 100, 100] In [17]: numbers Out[17]: [100, 3, 100, 7, 100, 13, 100, 19] In [18]: id(numbers) Out[18]: 4434456648

Let’s delete all the elements in `numbers`, leaving the *existing* list empty:

In [19]: numbers[:] = [] In [20]: numbers Out[20]: [] In [21]: id(numbers) Out[21]: 4434456648

Deleting `numbers`’ contents (snippet `[19]`) is different from assigning `numbers` a *new* empty list `[]` (snippet `[22]`). To prove this, we display `numbers`’ identity after each operation. The identities are different, so they represent separate objects in memory:

In [22]: numbers = [] In [23]: numbers Out[23]: [] In [24]: id(numbers) Out[24]: 4406030920

When you assign a new object to a variable (as in snippet `[21]`), the original object will be garbage collected if no other variables refer to it.