Prev: Constructing lists | Next: List of lists

**List slicing**is a technique for**separating a list into parts**, each of them being a*sublist*of the original list- Sublists are
**new list objects**in memory and not simply different 'views' of the original list

- Slicing notation is as follows:

where:`slice = alist[[start]:[end]:[step]]`

- '
`start`

' is the index of the first element of the original list to be included in the slice - '
`end`

' is the index of the last element (**NOT**included in the slice) - '
`step`

' is the step for moving from start to end value

- '

- Note that -as will become clear in the examples-
*none of the start, end, step arguments is absolutely necessary*when slicing a list. - Also, keep in mind that slicing is important in understanding the processing of more advanced Python data structures. So, it is worth investing some more time on the slicing topic to grasp both the concept and the implementation.
- Reflect on the examples below and make sure that you understand how slicing works

- Slice L1[0:5] below contains 5 items with indices from 0 to 4

In [4]:

```
L1 = [i for i in range(ord('A'), ord('K'))]
print(L1)
L2 = L1[0:5]
L2
```

Out[4]:

- Slice spam[2:5] below contains 3 items: the 3rd, 4th and 5th item of the original list

In [16]:

```
spam = ['a','b','c','d','e']
spam2 = spam[2:5]
spam2
```

Out[16]:

- When 'start' values is missing, the
**value 0**is assumed

In [5]:

```
L1 = [2*i for i in range(-5,5)]
print(L1)
L2 = L1[:5] # Note that ':' must be included to denote slicing instead of simple indexing
L2
```

Out[5]:

- When 'end' value is missing, the
**value len()**is assumed - Therefore:
*the value len() is acceptable in slicing BUT NOT in indexing*

In [10]:

```
L1 = [i+2 for i in range(-5,5)]
print(L1,'\t',len(L1),'\n')
L2 = L1[5:]
print(L2)
print('The same:',L1[5:10])
```

- The 'step' value can be either
**positive or negative**, depending on how 'start' and 'end' values are positioned

In [12]:

```
L1 = [x for x in range(10)]
print(L1)
L2 = L1[3:10:2] # Note that the element with index '10' is NOT included in L2 slice
L2
```

Out[12]:

- Below 'start' is greater than 'end'; so, 'step' needs to be negative for the slicing to work right

In [13]:

```
L1 = [x for x in range(10)]
L3 = L1[10:2:-3]
L3
```

Out[13]:

- If 'start' and 'end' are both missing then
**a copy of the original list is created**

In [14]:

```
L1 = [x for x in range(10)]
L4 = L1[:]
L4
```

Out[14]:

- The 'step' defines how the index changes while slicing from 'start' to 'end'

In [15]:

```
L1 = [x for x in range(10)]
L5 = L1[::2]
L5
```

Out[15]:

- This slicing constructs a reverse copy of the original list. Do you see why?

In [16]:

```
L1 = [x for x in range(10)]
L6 = L1[::-1]
L6
```

Out[16]:

- Negative indexes are
**acceptable**in slicing as well. - The
**last element**of the list is considered to have index '**-1**'

In [17]:

```
L1 = [k for k in range(10)]
print(L1)
L2 = L1[-5:-1]
L2
```

Out[17]:

In [19]:

```
L1 = [k for k in range(10)]
L3 = L1[-1:-len(L1):-1]
L3
```

Out[19]:

In [41]:

```
L0 = [x for x in range(1,12)]
L1 = [2*k for k in range(11)]
print(L0,'\t', L1)
L2 = [L1[-i::-1] for i in L0]
L2
```

Out[41]:

- Combining slicing and assignment provides a flexible way to change and extend a list
- Note that in the following examples no new list is constructed but the items of the original list change (new values are assigned).

**Replace values in list**: when the slice is**of equal size**with the list of new values.

In [85]:

```
L1 = [1,2,3,4,5,6,7,8,9,10]
L1[0:3] = [101, 102, 103] # Values 1,2,3 are replaced by 101, 102, 103
L1
```

Out[85]:

**Replace and insert values**: when the slice is smaller than the list of new values.

In [42]:

```
L1 = [1,2,3,4,5,6,7,8,9,10]
L1[0:3] = [101, 102, 103, 104, 105] # Values 1,2,3 are replaced and 104, 105 are inserted
L1
```

Out[42]:

**Replace and delete values**: when the slice is bigger than the list of new values.

In [43]:

```
L1 = [1,2,3,4,5,6,7,8,9,10]
L1[0:3] = [101,102] # Values 1,2 are replaced but 3 is deleted
L1
```

Out[43]:

**Delete ONLY values**: when slicing and**assigning an empty list []**

In [44]:

```
L1 = [1,2,3,4,5,6,7,8,9,10]
L1[0:3] = [] # Values 1,2,3 are now simply deleted
L1
```

Out[44]:

**Insert ONLY new values**: by indexing an**'insertion point'**and assigning new values, these are only inserted (old values are intact)- An insertion point is indexed when
**slicing indexes are equal: 'start' = 'end'** - Then the list of new values is inserted
**before**item with index 'start'

In [45]:

```
L1 = [1,2,3,4,5,6,7,8,9,10]
L1[1:1] = [101] # Insertion point [1,1] is before element with index [1]
# The value 101 is inserted
L1
```

Out[45]:

In [46]:

```
L1 = [1,2,3,4,5,6,7,8,9,10]
L1[0:0] = [101,102] # Values 101,102 are inserted in the beginning
L1 # What if we write: L1[:] = [101,102] - Why?
```

Out[46]:

In [47]:

```
L1 = [1,2,3,4,5,6,7,8,9,10]
L1[len(L1):] = [11, 12, 13] # Extending the list with new values
L1
```

Out[47]:

See a table summarizing Python indexes and slices here

. Free learning material

. See full copyright and disclaimer notice