Slicing¶
~15 min ยท prerequisite: Strings and Lists
What you will be able to do¶
- Take a part of a string, list, or tuple with
start:stopand get a new value back. - Use negative indexes, omitted bounds, and a
stepto reverse or skip items. - Predict what a slice gives when its bounds fall outside the sequence, and tell a slice error apart from an index error.
The idea¶
In lesson 1 you read one character with an index, such as word[0]. A slice reads a range of items at once. You write it inside square brackets with a colon: sequence[start:stop]. The value of start is the position of the first item you want. The value of stop is the position where you stop, and that item is not included. So "Python"[0:2] gives "Py", which is the items at positions 0 and 1.
Either bound may be left out. If you omit start, the slice begins at the first item. If you omit stop, it runs to the end. The slice "Python"[:3] gives "Pyt", and "Python"[3:] gives "hon". The slice "Python"[:] gives a copy of the whole sequence.
Negative numbers count from the end, as they do for a single index. The item at -1 is the last item, so "Python"[-3:] gives "hon". This also works in the middle: "Python"[1:-1] gives "ytho".
A third part, the step, controls how many positions you move each time. The slice sequence[start:stop:step] takes every stepth item. The slice [::2] takes every second item, and [::-1] takes every item in reverse order. Reversing is a common use, because "abc"[::-1] gives "cba".
A slice always gives back a new value of the same type. A slice of a string is a string, and a slice of a list is a list. The original sequence does not change. Slicing a list also gives you a copy, so copy = nums[:] is one way to make an independent list.
A slice does not raise an error when its bounds fall outside the sequence. Bounds that are too large are cut down to the end, and bounds that are too small are cut to the start. A single index does raise an error in that case, as lesson 1 showed.
Worked example¶
letters = "abcdefgh"
print(letters[2:5])
print(letters[:3])
print(letters[-3:])
print(letters[::2])
print(letters[::-1])
nums = [10, 20, 30, 40, 50]
print(nums[1:4])
print(nums[10:])
Line by line, this is what Python does:
letters[2:5]starts at position 2, which isc, and stops before position 5. The result iscde.letters[:3]has no start, so it begins at the first item. The result isabc.letters[-3:]starts three items from the end, atf, and runs to the end. The result isfgh.letters[::2]has no start or stop and a step of 2. It takesa,c,e,g.letters[::-1]has a step of -1, so it walks backwards from the end. The result ishgfedcba.nums[1:4]gives the list items at positions 1, 2, and 3. Note that position 4 is excluded.nums[10:]starts past the end of the list. Python returns an empty list, and no error appears.
The output is:
Try it¶
The first block checks slices of a string. The second block checks slices of a list and that a slice is a new object. The third block checks steps and out-of-range bounds.
Common mistakes¶
-
Expecting the stop item to be included. The code
print("Python"[0:2])printsPy, notPyt. The item at position 2 is excluded. To include positions 0 to 2, write[0:3]. -
Using an index where a slice is needed. The code
word = "Python"followed byprint(word[10])gives:A single index must exist. A slice such as
word[10:]gives an empty string instead. -
Using a step of zero. The code
print([1, 2, 3][::0])gives:The step tells Python how far to move each time, so it must not be zero.
-
Expecting a slice to change the original. The code
nums = [1, 2, 3]followed bynums[0:2]andprint(nums)still shows[1, 2, 3]. A slice returns a new value. Assign it to a name if you want to keep it. -
Mixing up the order of the bounds. The slice
"Python"[4:1]gives an empty string, because the stop is before the start. Read the bounds as "from here, up to but not including there".
Practice¶
- Create
word = "scarlet". Assert thatword[0:3]equals"sca", and thatword[-2:]equals"et". - Create
nums = [1, 2, 3, 4, 5, 6]. Assert thatnums[2:]equals[3, 4, 5, 6], and thatnums[:2]equals[1, 2]. - Create
text = "abcdef". Assert thattext[::2]equals"ace", and thattext[1::2]equals"bdf". - Create
phrase = "level". Buildbackwardswith a slice. Assert thatphrase == backwards, which is a palindrome check. - Stretch: create
nums = [0, 1, 2, 3, 4, 5, 6, 7]. Assert thatnums[1:7:2]equals[1, 3, 5], and thatnums[::-2]equals[7, 5, 3, 1].
Solution
-
python word = "scarlet" assert word[0:3] == "sca" assert word[-2:] == "et" -
python nums = [1, 2, 3, 4, 5, 6] assert nums[2:] == [3, 4, 5, 6] assert nums[:2] == [1, 2] -
python text = "abcdef" assert text[::2] == "ace" assert text[1::2] == "bdf" -
python phrase = "level" backwards = phrase[::-1] assert phrase == backwards -
python nums = [0, 1, 2, 3, 4, 5, 6, 7] assert nums[1:7:2] == [1, 3, 5] assert nums[::-2] == [7, 5, 3, 1]
Recap¶
sequence[start:stop]gives the items fromstartup to, but not including,stop. Either bound can be omitted.- A third value,
sequence[start:stop:step], skips items, and a step of-1reverses the order. - A slice returns a new value of the same type, and it does not raise an error for bounds outside the sequence.