A complete guide to Python slicing operations

Do you often write several lines of loops just to "get the first few elements"? In order to reverse a list, do you have to manually spell it from back to front? In fact, Python has already prepared a Swiss Army Knife for you - Slice. With good use of it, the amount of code for processing sequence data can be reduced by more than half, and it reads more like natural language.

This article will use the most down-to-earth examples to take you from basics to advanced, and thoroughly master all the practical skills of Python slicing.


1. Introduction to slicing operation

Slicing is Python’s built-in specialization for sequence data (listtuplestrbytesetc.) designed subset extraction tool. It condenses "where to start, where to end, and how to jump" into one line of code. It is not only faster than ordinary loops, but also has a higher level of readability.

**Core idea: Use the least code to achieve the most accurate sequence cutting. **


2. Basic slicing syntax:[start:stop:step]

The structure of the slice is very simple, with three parameters separated by colons:

sequence[start:stop:step]

The meaning and default value of each parameter can be found in the following table:

ParametersFunctionDefault valueValue description
startStarting position (containing the element)0(Starting from the left end)Positive/negative integer
stopEnding position (not including this element)Sequence length (end at right end)Positive/negative integer
stepStep size, how many elements to skip each time1(Continuously taken)Non-zero positive/negative integer

2.1 The most commonly used basic examples

nums = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# 取前3个元素(start 默认0,stop=3,step 默认1)
print(nums[:3])   # [0, 1, 2]

# 取索引1到3的元素(不包含4,即下标1、2、3)
print(nums[1:4])  # [1, 2, 3]

# 从索引2开始,一直取到最后
print(nums[2:])   # [2, 3, 4, 5, 6, 7, 8, 9]

# 每隔一个元素取一个(步长2)
print(nums[::2])  # [0, 2, 4, 6, 8]

3. Advanced techniques: negative index, reversal and shallow copy

Just cutting forward is not enough. The following "black magic" is the secret to double your efficiency.

3.1 Negative index: No need to calculate the length anymore

Python supports indexing from right to left,-1represents the last element,-2is the second to last, and so on. This makes "taking the last few" very natural:

nums = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# 取最后3个
print(nums[-3:])    # [7, 8, 9]

# 取倒数第4到倒数第2个(不包含索引 -1 的 9)
print(nums[-4:-1])  # [6, 7, 8]

3.2 Negative step size: reverse sequence in one line

BundlestepIf set to a negative number, the slice will take values ​​from right to left. This is the simplest way to write inversion in Python:

nums = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
text = "Hello, World!"

# 完全反转列表和字符串
print(nums[::-1])   # [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
print(text[::-1])   # '!dlroW ,olleH'

# 反向每隔一个取一个
print(nums[::-2])   # [9, 7, 5, 3, 1]

3.3 Shallow copy:sequence[:]is the fastest way to copy

For mutable sequences (such as lists), use[:]You can quickly create a shallow copy, which is suitable for most one-dimensional list copy scenarios:

original = [1, 2, [3, 4]]
shallow_copy = original[:]

# 修改一维元素不会影响原列表
shallow_copy[0] = 999
print(original)      # [1, 2, [3, 4]]
print(shallow_copy)  # [999, 2, [3, 4]]

# 嵌套元素会受影响——这就是浅拷贝的特性
shallow_copy[2][0] = 666
print(original)      # [1, 2, [666, 4]]
print(shallow_copy)  # [999, 2, [666, 4]]

Note: Shallow copy only copies the outer container, and the internal sub-objects are still shared references. When encountering multi-level nested structures, you need to usecopy.deepcopy()Implement deep copy.


4. What data types does slicing support?

As long as the data is indexable, has length, and the elements are in order, it can be sliced. Below are the three most common ones.

4.1 List

fruits = ['apple', 'banana', 'cherry', 'date', 'elderberry']
print(fruits[1:4])   # ['banana', 'cherry', 'date']

4.2 Tuple

colors = ('red', 'green', 'blue', 'yellow', 'purple')
print(colors[::2])   # ('red', 'blue', 'purple')

4.3 String

text = "2024-05-20 Python切片"
print(text[:10])     # '2024-05-20'

5. Slicing optimization of large sequences

Ordinary slicing will create a brand new sequence object. If you face hundreds of thousands or even millions of data, the memory pressure will be huge. At this time, two "memory-saving" alternatives can be used.

5.1 itertools.islice: Lazy slice generator

isliceReturns a generator that only calculates the next element when needed, without copying the entire slice contents into memory at once:

import itertools

large_list = list(range(1_000_000))

# 标准切片立刻创建出一个 10 个元素的新列表
small = large_list[10:20]

# islice 返回生成器,几乎不占额外内存
sliced = itertools.islice(large_list, 10, 20)
for item in sliced:
    print(item, end=' ')   # 10 11 ... 19

5.2 memoryview: A "zero-copy" view of binary data

deal withbytesorbytearrayhour,memoryviewYou can directly operate the memory area of ​​the original data, which not only saves memory, but also supports in-situ modification:

data = bytearray(b'hello world')
mv = memoryview(data)

# 切片得到一个视图,不复制数据
sub_mv = mv[6:11]
print(sub_mv.tobytes())   # b'world'

# 通过视图修改,直接反映到原始数据
sub_mv[0] = ord('W')
print(data)               # bytearray(b'hello World')

6. Two practical slicing application scenarios

6.1 Handwrite a simple version of string trim

Python comes withstr.strip(), but using slicing to implement it yourself can deepen your understanding and consolidate your grasp of the judgment of the first and last elements:

def my_trim(s):
    # 去掉开头的空格:每次向前切掉一个字符
    while len(s) > 0 and s[0] == ' ':
        s = s[1:]
    # 去掉结尾的空格:每次向后切掉一个字符
    while len(s) > 0 and s[-1] == ' ':
        s = s[:-1]
    return s

# 验证
assert my_trim('hello ') == 'hello'
assert my_trim(' hello') == 'hello'
assert my_trim(' hello world ') == 'hello world'
assert my_trim('') == ''
assert my_trim('   ') == ''
print("所有测试通过!")

6.2 Divide large sequences into fixed-size chunks

When processing data in batches, it is often necessary to divide the list into small pieces and use slicing with the generator to do it in one line:

def chunker(seq, chunk_size):
    """将序列分成固定大小的块,返回生成器"""
    return (seq[pos:pos + chunk_size] for pos in range(0, len(seq), chunk_size))

# 把 0~24 按每 4 个分块
for chunk in chunker(range(25), 4):
    print(list(chunk))

7. Some things to pay attention to

  • No error will be reported if the index is out of bounds: For examplenums[100:200]will not causeIndexError, will only return an empty list.
  • stepMust not be 0: will be thrown directlyValueError
  • Frequent slicing may also slow down the program: Although single slicing is faster than looping, if you repeatedly cut the same large list in millions of loops, a large number of intermediate objects will still be generated. Try to cut it all at once or use a generator instead.

8. Summary

The essence of Python slicing is[start:stop:step]Three parameters, combined with positive and negative indexes, can solve 90% of sequence processing problems. It is simple, intuitive and efficient, and is a basic skill that must be practiced from entry to advanced.

Next time you are processing a list, string, or tuple, ask yourself: "Can it be simplified by using slices?" It is possible that one line of code can save you the entire loop.