Home > Articles

  • Print
  • + Share This
This chapter is from the book

This chapter is from the book

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.

  • + Share This
  • 🔖 Save To Your Account