# A Beginner’s guide to Python slicing

In this tutorial, you’ll understand how slicing works in Python and how it can be used to manipulate sequences like strings, lists, and tuples.

We’ll also demonstrate how Python’s slice object creates a slice that can be used to slice a sequence.

This knowledge will give you a powerful tool to access a number of items from a sequence, manage them in ways such as deleting multiple items or inserting multiple items, and much more.
Ready to dive in? Let’s go!

## Python Indexing and Slicing

Indexing and slicing are two integral concepts of Python, utilized for accessing elements in sequences such as lists, strings, and tuples. Here, we’ll discuss what each concept is, and provide examples to help you understand.

### Indexing

Indexing refers to accessing individual elements of a sequence using their index. Indices in Python start from 0 for the first element, and increase by one for each subsequent element. For example:

```data = ['a', 'b', 'c', 'd', 'e']
print(data[1])
```

Output:

```'b'
```

In this code, we’re using indexing to access the second element (‘b’) in the list.

### Slicing

Slicing, on the other hand, allows you to obtain a subset (or a ‘slice’) of a sequence. It’s not limited to single elements – it can handle multiple items, all in one go. For instance:

```print(data[1:3])
```

Output:

```['b', 'c']
```

Here we’re using slicing to get a section of the list. `data[1:3]` returns a new list containing the items from index 1 (inclusive) to 3 (exclusive).

## How does Slicing Works in Python?

There are two primary methods of slicing in Python: using the slicing notation and using the `slice()` function.

Here’s an overview of each:

### Slicing Notation

Slicing notation is probably what you’re most familiar with. It’s straightforward and easy to read.

Slicing notation looks like this: `my_list[start:stop:step]`.

• `start`: The index where the slice starts. If omitted, it will start from the beginning.
• `stop`: The index where the slice will stop. This index is not included in the slice.
• `step`: The amount by which the index increases. If omitted, it will default to 1.

Example 1:

```my_list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(my_list[1:7:2])
```

Output:

```[1, 3, 5]
```

This slice returns a list containing the elements from index 1 up to but not including index 7, stepping by 2.

Example 2:

`print(my_list[2:])`

Output:

`[3, 4, 5, 6, 7, 8, 9]`

This slice starts from the element at index 2 and includes all elements to the end of the list.

Example 3:

`print(my_list[:3])`

Output:

`[1, 2, 3]`

This slice includes all elements from the start of the list up to (but not including) the element at index 3.

Example 4:

`print(my_list[2::2])`

Output:

`[3, 5, 7, 9]`

This slice starts from the element at index 2 and steps through the list with a step of 2, so it includes every other element from index 2 to the end of the list.

Example 5:

`print(my_list[:3:2])`

Output:

`[1, 3]`

This slice starts from the beginning of the list and ends before index 3, taking every other element (step of 2).

### `slice()` Function

The `slice()` function creates a slice object, which you can then use to slice a sequence. This function takes the same three arguments as the slicing notation (start, stop, step).

Here’s the same example using the `slice()` function:

```my_list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
my_slice = slice(1, 7, 2)
print(my_list[my_slice])```

Output:

`[1, 3, 5]`

One advantage of the `slice()` function is that you can create a slice object once and use it multiple times, which can make your code cleaner and more efficient if you’re applying the same slice in multiple places.

Furthermore, using the `slice()` function can be useful when the slicing indices are computed or come from variables, especially in scenarios when you’re defining a function or a method that needs to perform slicing and you want to parameterize the slice boundaries.

## Create Slice Objects

Let’s look at how to create and use a slice object using the `slice` function.
Here is the general syntax for the `slice` function in Python:

```slice(stop)
slice(start, stop, step)
```
• `start`: This is optional. An integer number specifying at which position to start the slicing. The default is None.
• `stop`: An integer number specifying at which position to end the slicing.
• `step`: This is optional. An integer number specifies the step of the slicing. The default is None.

Let’s look at some examples:

```my_list = [1, 2, 3, 4, 5, 6, 7, 8, 9]
slice_obj = slice(2, 6)

# Use the slice object
print(my_list[slice_obj])
```

Output:

```[3, 4, 5, 6]
```

Here, we’ve created a slice object with `start=2` and `stop=6`. We then used this slice object to slice the list, resulting in a new list from the third to the sixth element.
Slice objects can also be used with strings:

```text = "Hello, World!"
slice_obj = slice(7, 12)

# Use the slice object
print(text[slice_obj])
```

Output:

```World
```

In this example, we created a slice object and used it to slice a string, producing the substring ‘World’.

In most cases, the regular slicing notation is sufficient and more common, as it’s typically easier to read and understand.

## How to Slice a String to Get a Substring?

Just like we slice lists, we can use the same slicing technique with strings to extract substrings. Here’s how to slice a string:

```text = "Hello, World!"
substring = text[7:12]
print(substring)
```

Output:

```'World'
```

In this example, we sliced the string starting from index 7 and ending before index 12 to extract the substring ‘World’.

## How to Slice a String with Step Size?

Step size, often referred to as ‘stride’, is the third parameter in Python slicing that governs how many items to skip between each item included in the slice.

Let’s dive into how to use step size when slicing strings.

```text = "Python Programming"
substring = text[::2]
print(substring)
```

Output:

```'Pto rgamn'
```

In this Python example, we used a step size of 2 which results in every second character of the string.

We start from the beginning (since start is not specified), go until the end (since end is not specified), and select every second character.

## How to Slice a String from End to Start?

Python’s slicing mechanism also allows for slicing a string from the end to the start. This is achieved by using negative step values. Here’s how it’s done:

```text = "Hello, Python!"
reverse_text = text[::-1]
print(reverse_text)
```

Output:

```'!nohtyP ,olleH'
```

In this example, we’ve sliced the string from the end to the start. The `[::-1]` slice works by starting from the end of the string (since the start and end indices are not specified, the full string is used), and moving backwards, as indicated by the step size of -1.

## How to Slice Using Negative Index?

We can use a negative number as a start index to start slicing from a specific position from the end.

Let’s look at how to slice using a negative index.

### Negative Indexing with Strings

```text = "Hello, World!"
substring = text[-6:-1]
print(substring)
```

Output:

```'World'
```

In this example, we used negative indexing to extract the substring ‘World’. The slice `[-6:-1]` starts at the sixth character from the end (‘W’) and stops before the last character (‘!’).

We can also use a negative number in the stop index:

```text = "Hello, World!"
substring = text[-6:-7:-1]
print(substring)```
Output:
`W`

### Negative Indexing with Lists

The same principle applies to lists:

```my_list = [1, 2, 3, 4, 5, 6, 7, 8, 9]
slice_list = my_list[-4:-1]
print(slice_list)
```

Output:

```[6, 7, 8]
```

Here, we’ve sliced a list using negative indices. The slice `[-4:-1]` starts at the fourth item from the end (6) and stops before the last item (9).

## How to Slice a List or Tuple?

In Python, slicing is not only applicable to strings. We can use the same technique to slice sequences like lists and tuples. Let’s illustrate this with some examples.

### Slicing a List

```my_list = [1, 2, 3, 4, 5, 6, 7, 8, 9]
slice_list = my_list[2:6]
print(slice_list)
```

Output:

```[3, 4, 5, 6]
```

In this example, we’ve sliced a list starting from index 2 and ending before index 6.

### Slicing a Tuple

Slicing a tuple follows the same syntax:

```my_tuple = ('a', 'b', 'c', 'd', 'e')
slice_tuple = my_tuple[1:4]
print(slice_tuple)
```

Output:

```('b', 'c', 'd')
```

In this example, we’ve sliced a tuple starting from index 1 and ending before index 4.

## Copying Using Slicing

You can use slicing to create a copy of a sequence. The syntax `[:]` or `[::]` is often used for this purpose. This will create a new list that contains all elements from the original list.

Let’s look at an example:

```original_list = [1, 2, 3, 4, 5]
copied_list = original_list[:]
print(copied_list)```

Output:

`[1, 2, 3, 4, 5]`

Here, we copied `original_list` using slicing and assigned it to `copied_list`.

Now, `copied_list` is a separate list that has the same elements as `original_list`.

This way of copying is useful because it creates a new list independent of the original. So, changes to the original list will not affect the copied list, and vice versa.

```original_list[0] = 'a'
print("Original:", original_list)
print("Copied:", copied_list)```

Output:

```Original: ['a', 2, 3, 4, 5]
Copied: [1, 2, 3, 4, 5]```

As you can see, modifying `original_list` does not affect `copied_list`.

## Assign Values to a Slice (Slice Assignment)

Python provides the ability to assign values to a slice of a list. This operation is often referred to as ‘slice assignment’.

### How to Update Items?

You can use the slice assignment to change a portion of the list.
Here’s an example to demonstrate this:

```my_list = [1, 2, 3, 4, 5, 6]

my_list[1:4] = ['a', 'b', 'c']
print(my_list)
```

Output:

```[1, 'a', 'b', 'c', 5, 6]
```

In this example, we assigned the list `['a', 'b', 'c']` to the slice from index 1 to 4 of `my_list`.

As a result, the second, third, and fourth elements of `my_list` were replaced.

### How to Append Items?

You can append new items to an existing list using slice assignment without overwriting any items like this:

```my_list = [1, 2, 3, 4, 5]
my_list[len(my_list):] = [6, 7, 8]
print(my_list)
```

Output:

```[1, 2, 3, 4, 5, 6, 7, 8]
```

In this example, `my_list[len(my_list):]` is an empty slice starting at the end of the list.

By setting this slice to `[6, 7, 8]`, we append these items at the end of the list without overwriting any existing items.
This is essentially equivalent to using the `list.extend()` method or the `+=` operator, but it demonstrates the versatility of Python’s slice assignment.

### How to Insert Items in the Middle?

You can insert items in the middle of a list without removing any existing elements using slice assignment.
Here’s how you can do it:

```my_list = [1, 2, 4, 5]
my_list[2:2] = [2.5, 3]
print(my_list)
```

Output:

```[1, 2, 2.5, 3, 4, 5]
```

In this example, `my_list[2:2]` is an empty slice at the position where we want to insert the items. By setting this slice to `[2.5, 3]`, we insert these items at this position without overwriting any existing items.

The slice’s start and end are at the same index, so no elements from the original list are removed or replaced.

### How to Delete Items?

By setting a slice of a list to an empty list, you can effectively delete those items.
Here’s how it works:

```my_list = [1, 2, 3, 4, 5, 6, 7, 8, 9]
my_list[2:5] = []
print(my_list)
```

Output:

```[1, 2, 6, 7, 8, 9]
```

In this example, we deleted a slice of the list from index 2 to index 5. By setting this slice to an empty list, we removed these items from the list.
Keep in mind that this operation modifies the original list.