Slice Notation – A Simple Illustrated Guide

Summary: Slicing is a Python concept to extract a subsequence from a string or list—that lies within a start and stop index range. There are two syntactical ways to define a slice. (1) The extended slice notation makes use of a colon : in string_name[start:stop:step]. (2) The slice() constructor defines the index range in string_name[slice(start:stop:step)].

Here are some basic examples:

Exercise: Create two more examples in the interactive code shell.

Let’s learn about the slicing notation in a step-by-step manner.

Fundamentals Of Indexing

Before we dive into our discussion on slice notation in Python, let us have a quick look at what are indexes and how indexing works.

An index can be considered as the position of an element in an ordered data type (like a file or tuple). A string can be considered as a list of characters with each character having an index.

  • Indexing starts from zero to the length-1.
  • Python also supports negative indexing.

Let’s visualize indexing with the help of a diagram:

Now that we have an idea about indexes, let us dive into our topic, i.e., the slice notation.

Introduction To Slicing

Definition:

Slicing refers to a concept in Python that allows us to extract a part of a string or a list or any other sequence based on a given start and stop index.

Syntax:

  • Slicing uses [] with start, stop and step arguments separated by : notation.
  • start determines the index from which slicing/extraction of elements of the string/sequence begins.
  • If the start index is not specified, it is considered 0.
  • stop determines the last index until which slicing is performed, however, the stop/last index is excluded while generating the substring. This means that the last index that is taken into consideration while generating the output (substring) is stop-1. This is a very important point to remember to avoid unexpected outputs and bugs in code.
  • If the stop index is not specified, it is considered the length of the entire string or the given sequence.
  • step determines the increment between each index while slicing the sequence.
  • It is an optional argument. As a matter of fact, all three arguments are optional. We will soon discover how!
  • If the step is not specified it is considered to have a default value of 1, i.e. an increment of 1 between the indexes.

Example:

Please follow the example given below to have a look at the concepts discussed above. (Please ensure that you read the comments along with the code to have a better grip on the concepts.)

name = "FINXTER"
# [start:stop] --> items from start through stop-1
print(name[1:6])
# [:stop] --> items from the beginning of string through stop-1 
print(name[:6])
# [start:] --> items from start through end of string
print(name[1:])
# [start:stop:step] --> items from start through stop with step-size
print(name[1:6:2])
# Entire String!
print(name[:])

Output:

INXTE
FINXTE
INXTER
IXE
FINXTER

Step Size In Slicing

Though the step size is optional while slicing yet it has several applications and advantages. Therefore let us discuss some of the use cases that justify the importance of step size while slicing a sequence.

Use Case 1: Custom Increment Between Indexes While Slicing

As mentioned earlier if the step size is not specified then the increment between the indexes within the specified range is considered to be 1. This means that all the indexes within the specified range/slice of a given string will be taken into account and the entire substring will be generated as output without skipping any element in between. However, if we want to generate a string such that the value in between the indexes is incremented by any value other than 1 then we can use the step-size to specify such increments. In other words, the step size can be used to skip indexes within the specified slice.

Let us consider an example to understand how we can define a step-size and generate the desired output.

Example: Given the string “FPIYNTXHTOENR”; how to extract the elements at the even positions / odd indexes (considering the first position as 1)?

name = "FPIYNTXHTOENR"
print(name[1:12:2])

Output:

PYTHON

Though the above program is self-explanatory; let us have a look at the following diagram to visualize the above snippet so that the concept of step-size is crystal clear.

Use Case 2: Negative Step Size

Slicing provides us with the facility of negative step size. Therefore you can slice through a sequence or a string in the reverse direction using the negative step size. This can be instrumental in operations like reversing a string.

Example: Given the string “MADAM”; check if the string is a palindrome using a negative step size.

# String which reads the same backward as forward is a Palindrome string
name = "MADAM"
# Reversing the string using a negative step-size
palindrome = (name[::-1])
if name == palindrome:
  print(palindrome," is a Palindrome String. ")

Output:

MADAM  is a Palindrome String.

Slicing Through Negative Indices

Just like the negative step size, slicing also provides us with the added advantage of extracting substrings using the negative index of the individual characters in the string. Let us have a look at the following example to understand how slicing works with negative indices:

Example:

Let us use negative indices to slice the above string. Please follow the code along with the comments given below:-

string = "HELLO WORLD"
# [-start:-stop]
print(string[-11:-6])
# [:stop]
print(string[:-6])
# [start:]
print(string[-5:])
# Entire String using negative Indexing
print(string[-11:])
# [start:stop:step]
print(string[-11:-6:2])
# -Index and -Step to slice and reverse string
print(string[-1:-6:-1])

Output:

HELLO
HELLO
WORLD
HELLO WORLD
HLO
DLROW

Using The slice() Constructor

In the above examples, we have actually used a slice() object using a : notation within square brackets []. The slice() is an inbuilt constructor that is used to create a slice object which represent a subset of an entire sequence.

The Syntax for using the slice object is:

  • Both syntaxes are supported in Python while using the slice() object.
  • To substitute an argument with an empty entry, you can use None. For example to replicate string[1:] you can use string[slice(1, None)]

Since we already have an idea about indexing and slicing, let us contrast and compare the slice() object and the basic : based slice notation in Python.

  • string_name[slice(start, stop, step)] is equivalent to string_name[start:stop:step] where start, stop and step arguments have a similar meaning in both cases. However slice() objects have a slightly different behaviour based on the number of arguments.

The best way of comparing the two notations is to visualize them with the help of examples. Thus, let us dive into the code given below to compare and contrast slicing using the slice() and Basic : notation –

name = "FINXTER"
print("Original String = ", name)
print("\nScenario 1")
# [start:stop] --> items from start through stop-1
print("Output Using : Notation >> ",name[1:6])
print("Output Using slice Object >> ",name[slice(1,6)])

print("\nScenario 2")
# [:stop] --> items from beginning of string through stop-1 
print("Output Using : Notation >> ",name[:6])
print("Output Using slice Object >> ",name[slice(6)])

print("\nScenario 3")
# [start:] --> items from start through end of string
print("Output Using : Notation >> ",name[1:])
print("Output Using slice Object >> ",name[slice(1,7)])

print("\nScenario 4")
# [start:stop:step] --> items from start through stop with step-size
print("Output Using : Notation >> ",name[1:6:2])
print("Output Using slice Object >> ",name[slice(1,6,2)])

print("\nScenario 5")
# Entire String!
print("Output Using : Notation >> ",name[:])
print("Output Using slice Object >> ",name[slice(7)])

Output:

Original String =  FINXTER

Scenario 1
Output Using : Notation >>  INXTE
Output Using slice Object >>  INXTE

Scenario 2
Output Using : Notation >>  FINXTE
Output Using slice Object >>  FINXTE

Scenario 3
Output Using : Notation >>  INXTER
Output Using slice Object >>  INXTER

Scenario 4
Output Using : Notation >>  IXE
Output Using slice Object >>  IXE

Scenario 5
Output Using : Notation >>  FINXTER
Output Using slice Object >>  FINXTER

Forgiving Syntax Of Slicing

Python is really forgiving when it comes to slicing because even if you specify an index that exceeds the actual maximum index of the sequence, you will not get an error and the output will be displayed on the screen without any hassle. Even if you start at an index that is not valid you won’t find an error, instead, python will simply return an empty string.

Let us have a look at the example given below which clarifies the forgiving syntax of slicing in Python:

name = "FINXTER"
# prints entire string
print(name[0:10000])
# prints empty string
print(name[10000:10000])
# prints the element at first index
print(name[0::10000])
# Using None is same as using a zero at beginning
# or Not specifying any arguement 
print(name[None:])
print(name[2:None])

Output:

FINXTER

F
FINXTER
NXTER

Slicing With Other Sequence Types

Until now we discussed slicing with respect to strings in all our examples. However, slicing works with every sequential data-type that can be indexed like a list or tuple. Let us have a look at the following program, which demonstrates slicing with respect to a list and a tuple.

Example:

li = ["apple","banana","Orange"]
tup = ("Python","Java","C++")

#slicing the list
print(li[slice(0,2,1)])
print(li[slice(1)])
print(li[slice(None)])

# slicing the tuple
print(tup[0:2:1])
print(tup[:1])
print(tup[::])

Output:

['apple', 'banana']
['apple']
['apple', 'banana', 'Orange']
('Python', 'Java')
('Python',)
('Python', 'Java', 'C++')

Conclusion

The key takeaways from this article are :

  1. Fundamentals of Indexing.
  2. Slicing using the [start:stop:step] notation.
  3. Slicing using the slice() object.
  4. Step Size and its use cases.
  5. Slicing using the negative Indices.
  6. Slicing of other sequential data types.

We have a similar blog article where Christian Mayer has discussed some of the most frequently asked questions on slicing. Please have a look at the article by following this link. I hope you found this article on slicing notation useful. Please subscribe and stay tuned for more interesting articles!

Where to Go From Here?

Enough theory, let’s get some practice!

To become successful in coding, you need to get out there and solve real problems for real people. That’s how you can become a six-figure earner easily. And that’s how you polish the skills you really need in practice. After all, what’s the use of learning theory that nobody ever needs?

Practice projects is how you sharpen your saw in coding!

Do you want to become a code master by focusing on practical code projects that actually earn you money and solve problems for people?

Then become a Python freelance developer! It’s the best way of approaching the task of improving your Python skills—even if you are a complete beginner.

Join my free webinar “How to Build Your High-Income Skill Python” and watch how I grew my coding business online and how you can, too—from the comfort of your own home.

Join the free webinar now!