Python List Slicing

Table of contents:

Python List Slicing

List slicing is a technique in which a range of items of a list can be accessed. The new list is a subset of the original list.

If x is a list, then x[p:q] returns the portion of x starting with index p and up to index q but not including q.

Table of contents:

For slicing, we use the format:


Remember that all the three fields are optional. The shortest slice notation in python is x[:], which is also exactly equivalent to the notation x[::].

Consider the list
x = [1, "python", 101, 7.8, -9, "java", 13].

Here, len(x), i.e., number of items is 7. This len(x) value will be handy in slicing.

index items index length = 7 0 1 2 3 4 5 6 -7 -6 -5 -4 -3 -2 -1 1 python 101 7.8 -9 java 13

Applying a slice [3:6] on this list, we will get an output of [7.8, -9, 'java']

We are coming to the details of how this works.

First determine the step value, if not given

Take the slice notation x[::]. Here, we get none of the values of start, stop and step. Now, having a slice notation in our hand, first we have to check the third field step. The value of step decides the workflow of the whole slice.

The notations [:], [::], [p:], [p:q], [:q], [p::], [p:q:], [:q:] have a common thing in them; the step value is absent.

Note: If step is None, or it is blank, or empty, its value defaults to 1.

So, the above mentioned slice notations translate to [::1], [::1], [p::1], [p:q:1], [:q:1], [p::1], [p:q:1], [:q:1].

A step value of zero is invalid.

After step, determine start and stop values, if not given

If step is positive, start value will be 0. This refers to the first item of the list; stop value will be the length of the list.

If step is negative, start value will be -1. This refers to the last item of the list; stop value will be -(length+1).

At this point, we have a slice notation in our hand where all the start, stop and step values are defined with values, for example: [p:q:r]

What [p:q:r] means actually

Take a list z = [11, 22, 33, 44, 55, 66, 77].

For a slice notation [2:5:1], the interpreter starts with the item at index 2 and stops at the item before index 5. So output of z[2:5:1] is [33, 44, 55]

Note that item at index 5 is not included.

So stop value somehow translates to stop before.
For a slice notation [5:2:-1], the interpreter starts with the item at index 5 and stops at the item before index 2 in reverse direction because of negative step value -1. So output of z[5:2:-1] is [66, 55, 44].

In the following, item at index 4 is not included, i.e., the item at stop index is not inclusive.

Note: The item at stop index will not be included in the output list.

When start index is omitted and step is positive, slicing starts from the beginning of the list. In this case start defaults to zero.

For any list, x[:4] is the same as x[0:4]

When stop index is omitted and step is positive, slicing starts from start index upto the end of the list. Default for stop, in this case, is the length of the list len(x).

x[4:] is the same as x[4:len(x)].

If x is a list or tuple, len(x) returns the number of items in it. If x is a string, len(x) returns the number of characters in it.

Note: Indexing returns an item, while slicing returns a list.

Copy a list by slicing

When both start and stop are omitted, the entire list is the output.

In this way, we can copy a list by slicing. Both the lists will have the exact same items, though their identities will be different. Also x[:] and x[::] are the same.

Note: The slice notation [:] and [::] can copy a tuple as done in case of lists.

For this list, x[-6:-4] and x[1:3] are the same.

The step value

While x[::] returns the entire list, x[::2] returns the alternate items beginning from index 0 upto the end of the list

x[::2] forces the interpreter to include the first item, discard the 2nd, include the 3rd, discard the 4rth... upto the end of list.

x[::3] forces the interpreter to include the first item, discard the 2nd and 3rd, include the 4rth, discard the 5th and 6th... upto the end of list.

x[1:6:2] translates to "start with item at index 1, include alternate items, stop before index 6",

Negative step value

A negative step value enables the slicing from the end to the beginning of a list.

Slice x[::-1] reverses the entire list.

A step of -2 in x[::-2] reverses the list with the alternate values.

Consider the slice x[-2::-4].

Here, start index is -2 (6th. item), stop index is - len(x) - 1 = -8 (because of negative step), step -4 forces every 4rth alternate items to include.

Note: Though there is no index -8, in slicing this works because counting stops before -8. In indexing, x[-8] will raise an IndexError.

If the start or stop indices are out of range, python will raise no error, and return an empty list silently. We must be careful about this behaviour of python while slicing.

Note that executing print(x[7]) will raise an IndexError, because there is no index 7.

Slice assignment

In the previous page, we modified lists by indexing.

In the above, we targeted the second item and modified it.

Since slicing returns a portion of the list, we can modify a part of the list by slice assignment.

index items slice

The slice num[1:4] targets the [20, 30, 40] part of the original list. This part is replaced by the assigned list [22, 33, 44].

Note: Since slicing returns a list, slice assignment requires a list.

Take another example. The slice z[0:2] targets the first two items ["php", "vb"].

So they are replaced by the assigned items ["python", "c++"].

Extending and shrinking a list by slice assignment

A list can be extended in the following way.

What is happening here? If we display the value of a[2:2], we get an empty list []. We assign a list ["ram", "rom"] to a[2:2]. Python inserts this new list at index 2 of list a. In this way, list a is extended. Note that no item is overwritten.

In the following, the list is extended by overwriting one item.

If we display the value of a[2:3], we get [3]. So, in statement
a[2:3] = ["ram", "rom"]
the target list [3] is replaced by the assigned list ["ram", "rom"]. So, item at index 2 is overwritten.

The following code shrinks a list by slice assignment.

a[0:2] targets the [1, 2] part. It is replaced by the assigned empty list []. Thus the list is shrinked.

The slice() function

That we know the basics of slicing, it will be easy for us to use the slice() function.

Python slice() also accepts three parameters, start, stop and step. The stop parameter is mandatory, other two are optional.

The function returns a slice object of 'slice' type.

When we pass one argument for slice(), python takes it as the stop value, inserts a None(which is actually 0) as start value, and another None as step value (which is actually 1).

Now, as our first_three slice is ready, we can apply it to any list.

Note: The slice() function returns a slice object.

Let us create a slice that always returns the last two items of any list.

When we pass two arguments for slice(), python takes first one as the start value, second one as the stop value, and inserts None(which is actually 1) as step value.

Obviously, to specifically mention start value, we have to include both start and stop values.

To specifically mention step value, we have to include all start, stop and step values.

The slice() function is somehow similar to the python range(), which also accepts three parameters start, stop and step, the stop being mandatory, other two are optional.

    # Summary

  • 01 Slicing works with [start:stop:step] notation.
  • 02 Default step is 1.
  • 03 if step is positive, start defaults to zero.
  • 04 if step is negative, start defaults to -1.
  • 05 if step is positive, stop defaults to len(list).
  • 06 if step is negative, stop defaults to -len(list)-1.
  • 07 Item at stop index is excluded.
  • 08 Negative step counts backwards.
  • 09 Slicing returns a list.
  • 10 Slice assignment requires a list.

--- x ---

Want to leave a message for me?