Slicing is a Python-specific concept for carving out a range of values from sequence types such as lists or strings.
It is one of the most popular Python features. To master Python, you must master slicing first. Any non-trivial Python code base relies on slicing. In other words, the time you invest now in mastering slicing will be repaid a hundredfold during your career.
[Intermezzo] Indexing Basics
To bring everybody on the same page, let me quickly explain indices in Python by example. Suppose, we have a string ‘universe’. The indices are simply the positions of the characters of this string.
The first character has index 0, the second character has index 1, and the i-th character has index i-1.
Quick Introduction Slicing
The idea of slicing is simple. You carve out a subsequence from a sequence by defining the start and end indices. But while indexing retrieves only a single character, slicing retrieves a whole substring within an index range.
Use the bracket notation for slicing with the start and end position identifiers. For example,
word[i:j] returns the substring starting from index
i (included) and ending in index
j (excluded). Forgetting that the end index is excluded is a common source of bugs.
You can also skip the position identifier before or after the slicing colon. This indicates that the slice starts from the first or last position, respectively. For example,
word[:i] + word[i:] returns the same string as
Python puzzle 1: What is the output of this code snippet?
x = 'universe' print(x[2:4])
The Step Size in Slicing
For the sake of completeness, let me quickly explain the advanced slicing notation [start:end:step]. The only difference to the previous notation is that it allows you to specify the step size as well. For example, the command ‘python'[:5:2] returns every second character up to the fourth character, i.e., the string ‘pto’.
Python puzzle 2: What is the output of this code snippet?
x = 'universe' print(x[2::2])
Overshooting Indices in Slicing
Slicing is robust even if the end index shoots over the maximal sequence index. Just remember that nothing unexpected happens if slicing overshoots sequence indices. Here is an example.
word = "galaxy" print(word[4:50])
Summary Python Slicing
Short recap, the slice notation s[start:end:step] carves out a substring from s. The substring consists of all characters between the two characters at the start index (inclusive) and the end index (exclusive). An optional step size indicates how many characters are left out from the original sequence. Here is an example:
s = 'sunshine' print(s[1:5:2]) #'us' print(s[1:5:1]) #'unsh'
Learn Slicing By Doing
Ok, so let’s train slicing a little bit. Solve the following puzzle in your head (and check the solution below).
Python Puzzle 3: What is the output of this code snippet?
# (Shakespeare) s = "All that glitters is not gold" print(s[9:-9]) print(s[::10]) print(s[:-4:-1])
Frequently Asked Questions
Let’s go a bit deeper into slicing to make sure that you are getting it 100%.
I have searched Quora to find all the little problems new Python coders are facing with slicing. I will answer six common questions next.
1) How to skip slicing indices (e.g. s[::2])?
The Python interpreter assumes certain default values for s[start:stop:step]. They are: start=0, stop=len(s), and step=1 (in the slice notation: s[::]==s[0:len(s):1]).
2) When to use the single colon notation (e.g. s[:]) and when double colon notation (e.g. s[::2])?
A single colon (e.g. s[1:2]) allows for two arguments, the start and the end index. A double colon (e.g. s[1:2:2]) allows for three arguments, the start index, the end index, and the step size. If the step size is set to the default value 1, we can use the single colon notation for brevity.
3) What does a negative step size mean (e.g. s[5:1:-1])?
This is an interesting feature in Python. A negative step size indicates that we are not slicing from left to right, but from right to left. Hence, the start index should be larger or equal than the end index (otherwise, the resulting sequence is empty).
4) What are the default indices when using a negative step size (e.g. s[::-1])?
In this case, the default indices are not start=0 and end=len(s) but the other way round: start=len(s)-1 and end=-1. Note that the start index is still included and the end index still excluded from the slice. Because of that, the default end index is -1 and not 0.
5) We have seen many examples for string slicing. How does list slicing work?
Slicing works the same for all sequence types. For lists, consider the following example:
l = [1, 2, 3, 4] print(l[2:]) # [3, 4]
Slicing tuples works in a similar way.
6) Why is the last index excluded from the slice?
The last index is excluded because of two reasons. The first reason is language consistency, e.g. the range function also does not include the end index. The second reason is clarity, e.g., here’s an example why it makes sense to exclude the end index from the slice.
customer_name = 'Hubert' k = 3 # maximal size of database entry x = 1 # offset db_name = customer_name[x:x+k]
Now suppose the end index would be included. In this case, the total length of the db_name substring would be k + 1 characters. This would be very counter-intuitive.
Play with Examples
Here are the solutions to the puzzles in this article.