Python’s slice notation is straightforward enough, but it does have some strange edge cases.

Check out the following Python code:

>>> x = [1, 2, 3]
>>> x[0:100]
[1, 2, 3]
>>> x[100:]
[]

WAT! Why is Python doing this?

In both cases, we’re asking for an out of range slice index. Rather than throw an IndexError, in Python “slice indices are handled gracefully.”

When we ask for an upper bound that is too large, Python defaults to returning the length of the string. So x[0:100] is really x[0:len(x)] which results in x[0:2] which is [1, 2, 3].

In the second case, x[100:] we’re asking to start at index position 100 and proceed until the end. In this case, Python will return an empty string ''.

Takeaways

Per the Zen of Python, “practicality beats purity” which is on display here. Python defaults to these behaviors in order to be helpful.

The slice notation is a powerful feature in Python for creating substrings. Just be aware of these edge cases regarding out-of-range indexes!