展开菜单
首页 精品内容 本月促销 装机必备 Windows PDF教程 macOS软件 IOS软件 Android AI 专题
全部分类

当前位置:

首页 > 编程开发 > Python基础指南之列表切片操作的高级应用场景

Python基础指南之列表切片操作的高级应用场景

Python列表切片支持永不越界的访问(安全返回空列表),可创建浅拷贝,实现原地修改长度、插入删除元素,支持带步长赋值与反转序列,还能用于降采样、批量交换等操作,是Python列表的核心特性,极大提升编程效率。

本文目录

    聊到Python列表,就绕不开一个堪称“核武器”的特性——切片(Slice)。如果你用过Ja va或C++,一定还记得用循环提取子数组时那种繁琐的体验。而在Python里,一行 lst[2:8:2] 就能完成那些语言需要五六行代码才能搞定的事。

    Python基础指南之列表切片操作的高级应用场景

    但切片远不止“取一段数据”这么简单。它还能原地修改列表长度、反转序列、优雅地处理边界情况、实现高效的批量赋值。这篇文章就来系统地梳理一下切片的所有高级应用场景,看看它到底能玩出多少花样。

    一、切片的基础回顾与深入理解

    1.1 完整语法长什么样

    lst = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    
    # 完整语法:lst[start:stop:step]
    # start:起始索引(包含),默认:step>0时为0,step<0时为-1
    # stop:结束索引(不包含),默认:step>0时为len(lst),step<0时为-len(lst)-1
    # step:步长,默认1(不能为0)
    
    # 从索引2到索引7(步长为2)
    print(lst[2:7:2])  # [2, 4, 6]
    
    # 从索引8到索引2(反向步长为2)
    print(lst[8:2:-2])  # [8, 6, 4]
    

    1.2 默认值的完整规则

    lst = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    
    # 当step > 0(正向)时:
    # - start默认值 = 0
    # - stop默认值 = len(lst)
    
    # 以下等价:
    print(lst[0:10:1])  # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    print(lst[::1])     # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    print(lst[:])       # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    print(lst[0::1])    # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    print(lst[:10:1])   # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    
    # 当step < 0(反向)时:
    # - start默认值 = len(lst) - 1(即-1,最后一个元素)
    # - stop默认值 = -len(lst) - 1(即取到最前面)
    
    # 以下等价:
    print(lst[::-1])    # [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
    print(lst[-1:-11:-1])  # [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
    

    1.3 参数的计算规则

    # 理解切片中的索引计算
    lst = [10, 20, 30, 40, 50, 60, 70, 80]
    # 索引:0   1   2   3   4   5   6   7
    
    # 规则:lst[start:stop:step] 包含索引 start, start+step, start+2*step, ...
    # 直到达到或越过 stop
    
    # 例:lst[1:6:2]
    # 索引序列:1, 1+2=3, 3+2=5 → 索引1, 3, 5
    # 下一个 5+2=7 ≥ stop=6,停止
    print(lst[1:6:2])  # [20, 40, 60]
    
    # 例:lst[6:1:-2]
    # 索引序列:6, 6-2=4, 4-2=2 → 索引6, 4, 2
    # 下一个 2-2=0 ≤ stop=1,停止
    print(lst[6:1:-2])  # [70, 50, 30]
    
    # 核心记忆:step的正负决定方向,包含start不包含stop
    

    二、切片的强大特性

    2.1 永不越界——最实用的特性

    lst = [1, 2, 3, 4, 5]
    
    # 无论start和stop有多大或多小,切片都不会报错
    print(lst[0:100])     # [1, 2, 3, 4, 5](自动截断)
    print(lst[-100:3])    # [1, 2, 3]
    print(lst[10:20])     # [](start超出范围,返回空列表)
    print(lst[-10:-20])   # [](空范围,返回空列表)
    print(lst[100:0])     # [](start > stop,返回空列表)
    
    # 这就是为什么切片比索引更适合处理边界模糊的情况
    # 索引访问:越界就报错
    # lst[100]  # IndexError
    
    # 切片访问:越界就截断或返回空,永不出错
    # 这个特性让很多边界处理的代码变简单了
    

    2.2 切片创建的是浅拷贝

    original = [1, 2, 3]
    sliced = original[:]  # 创建副本
    
    # 修改原列表不影响切片
    original[0] = 999
    print(original)  # [999, 2, 3]
    print(sliced)    # [1, 2, 3]
    
    # 但对于嵌套列表,内层对象是共享的
    nested = [[1, 2], [3, 4]]
    copy_nested = nested[:]
    
    nested[0][0] = 999
    print(nested)       # [[999, 2], [3, 4]]
    print(copy_nested)  # [[999, 2], [3, 4]](内层共享!)
    
    # 如果需要完全独立的副本,用copy.deepcopy
    import copy
    deep = copy.deepcopy(nested)
    nested[0][0] = 111
    print(nested)  # [[111, 2], [3, 4]]
    print(deep)    # [[999, 2], [3, 4]](不受影响)
    

    2.3 切片的独立性——但对切片赋值会影响原列表

    # 用切片获取一个视图...等等,Python的切片返回的是新列表,不是视图!
    # 这一点和NumPy不一样
    
    lst = [1, 2, 3, 4, 5]
    view = lst[1:4]  # 这是一个新列表!
    view[0] = 999
    print(lst)   # [1, 2, 3, 4, 5](原列表不变)
    print(view)  # [999, 3, 4]
    
    # 这一点和NumPy数组的行为不同
    import numpy as np
    arr = np.array([1, 2, 3, 4, 5])
    arr_view = arr[1:4]  # NumPy的切片是视图(共享底层数据)
    arr_view[0] = 999
    print(arr)      # [  1 999   3   4   5](原数组也被改了!)
    print(arr_view) # [999   3   4]
    
    # Python列表使用这种方式原地修改切片区域:
    lst[1:4] = [999, 999, 999]
    print(lst)  # [1, 999, 999, 999, 5](原列表被修改了)
    

    这是Python列表和NumPy数组的一个重要区别。Python列表的切片总是创建新列表,而NumPy的切片是视图。在数据科学领域切换时,这一点特别值得注意。

    三、用切片原地修改列表

    3.1 切片赋值:替换任意范围的元素

    nums = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    
    # 替换中间一段
    nums[3:7] = [30, 40, 50, 60]
    print(nums)  # [0, 1, 2, 30, 40, 50, 60, 7, 8, 9]
    
    # 替换为更长的序列——列表变长!
    nums[3:7] = [30, 40, 50, 60, 70, 80]
    print(nums)  # [0, 1, 2, 30, 40, 50, 60, 70, 80, 7, 8, 9]
    
    # 替换为更短的序列——列表变短!
    nums[3:9] = [300]
    print(nums)  # [0, 1, 2, 300, 7, 8, 9]
    
    # 替换为空——删除一段元素
    nums[2:5] = []
    print(nums)  # [0, 1, 7, 8, 9]
    

    3.2 在任意位置插入元素

    nums = [1, 5, 9]
    
    # 在索引1处插入多个元素
    nums[1:1] = [2, 3, 4]
    print(nums)  # [1, 2, 3, 4, 5, 9]
    
    # 在开头插入
    nums[:0] = [-1, 0]
    print(nums)  # [-1, 0, 1, 2, 3, 4, 5, 9]
    
    # 在末尾插入
    nums[len(nums):] = [10, 11]
    print(nums)  # [-1, 0, 1, 2, 3, 4, 5, 9, 10, 11]
    
    # 在中间插入
    mid = len(nums) // 2
    nums[mid:mid] = ['中']
    print(nums)  # [-1, 0, 1, 2, 3, 4, '中', 5, 9, 10, 11]
    

    3.3 删除任意范围的元素

    nums = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    
    # 删除前3个
    nums[:3] = []
    print(nums)  # [3, 4, 5, 6, 7, 8, 9]
    
    # 删除后3个
    nums[-3:] = []
    print(nums)  # [3, 4, 5, 6]
    
    # 删除偶数位置(每隔一个)
    nums[::2] = []
    print(nums)  # [4, 6]
    
    # 注意:`del lst[::2]` 和 `lst[::2] = []` 效果相同
    nums = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    del nums[::2]
    print(nums)  # [1, 3, 5, 7, 9]
    

    3.4 带步长的切片赋值——有严格限制

    nums = [0, 1, 2, 3, 4, 5]
    
    # 带步长的切片赋值:右边的长度必须和切片结果长度一致!
    nums[::2] = [10, 20, 30]  # 3个元素对3个位置
    print(nums)  # [10, 1, 20, 3, 30, 5]
    
    # ❌ 长度不匹配会报错
    # nums[::2] = [10, 20]  # ValueError: attempt to assign sequence of size 2 to extended slice of size 3
    # nums[::2] = [10, 20, 30, 40]  # ValueError
    
    # 这个限制只在步长≠1时存在
    # 步长为1的切片(lst[a:b])赋值不受此限,可以改变列表长度
    

    四、切片的实用技巧大全

    4.1 反转序列

    # 方式一:[::-1](最常用)
    lst = [1, 2, 3, 4, 5]
    reversed_lst = lst[::-1]
    print(reversed_lst)  # [5, 4, 3, 2, 1]
    
    # 方式二:reversed()(返回迭代器,不创建新列表)
    for item in reversed(lst):
        print(item, end=' ')  # 5 4 3 2 1
    print()
    
    # 方式三:list.reverse()(原地反转,不创建新列表)
    lst.reverse()
    print(lst)  # [5, 4, 3, 2, 1]
    
    # 性能对比
    # lst[::-1]:创建新列表,O(n)内存
    # lst.reverse():原地反转,O(1)额外内存
    # reversed(lst):懒迭代,O(1)额外内存
    
    # 反向字符串
    text = 'hello world'
    print(text[::-1])  # dlrow olleh
    

    4.2 浅拷贝的多种写法

    original = [1, 2, 3, 4, 5]
    
    # 三种等价的浅拷贝方式
    copy1 = original[:]
    copy2 = original.copy()
    copy3 = list(original)
    
    # 它们创建的都是浅拷贝
    print(copy1 == copy2 == copy3)  # True
    print(copy1 is original)        # False
    
    # 哪种最快?实际测试:
    import time
    
    n = 1000000
    lst = list(range(100))
    
    start = time.perf_counter()
    for _ in range(n):
        c = lst[:]
    print(f'[:]      {time.perf_counter() - start:.3f}秒')
    
    start = time.perf_counter()
    for _ in range(n):
        c = lst.copy()
    print(f'.copy()  {time.perf_counter() - start:.3f}秒')
    
    start = time.perf_counter()
    for _ in range(n):
        c = list(lst)
    print(f'list()   {time.perf_counter() - start:.3f}秒')
    
    # .copy()通常最快(因为是直接的C方法调用),[:]次之,list()最慢
    

    4.3 每隔N个取一个元素

    lst = list(range(30))
    
    # 每隔2个取一个(所有偶数索引)
    print(lst[::2])
    # [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28]
    
    # 每隔3个取一个
    print(lst[::3])
    # [0, 3, 6, 9, 12, 15, 18, 21, 24, 27]
    
    # 从第2个开始,每隔4个取一个
    print(lst[1::4])
    # [1, 5, 9, 13, 17, 21, 25, 29]
    
    # 实际应用:对列表进行降采样
    def downsample(lst, factor):
        """将列表降采样为原来的1/factor"""
        return lst[::factor]
    
    original = list(range(100))
    reduced = downsample(original, 10)
    print(reduced)  # [0, 10, 20, 30, 40, 50, 60, 70, 80, 90]
    

    4.4 批量交换元素位置

    # 将列表的前半部分和后半部分互换
    def swap_halves(lst):
        mid = len(lst) // 2
        # 注意:直接赋值会改变原列表
        lst[:] = lst[mid:] + lst[:mid]
    
    nums = [1, 2, 3, 4, 5, 6]
    swap_halves(nums)
    print(nums)  # [4, 5, 6, 1, 2, 3]
    
    # 循环左移k位
    def rotate_left(lst, k):
        k %= len(lst)
        lst[:] = lst[k:] + lst[:k]
    
    nums = [1, 2, 3, 4, 5, 6, 7]
    rotate_left(nums, 2)
    print(nums)  # [3, 4, 5, 6, 7, 1, 2]
    
    # 循环右移k位
    def rotate_right(lst, k):
        k %= len(lst)
        lst[:] = lst[-k:] + lst[:-k]
    
    nums = [1, 2, 3, 4, 5, 6, 7]
    rotate_right(nums, 2)
    print(nums)  # [6, 7, 1, 2, 3, 4, 5]
    

    4.5 列表“压缩”——去除特定位置的元素

    # 去除所有偶数索引位置的元素
    lst = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
    del lst[::2]
    print(lst)  # ['b', 'd', 'f', 'h']
    
    # 去除所有奇数索引位置的元素
    lst = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
    del lst[1::2]
    print(lst)  # ['a', 'c', 'e', 'g']
    
    # 保留前3个和后3个,删除中间的
    lst = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    lst[3:-3] = []
    print(lst)  # [0, 1, 2, 7, 8, 9]
    

    五、切片的高级应用场景

    5.1 数据分页

    def paginate(items, page, page_size):
        """用切片实现数据分页"""
        start = (page - 1) * page_size
        end = start + page_size
        return items[start:end]
    
    # 模拟数据库查询结果
    all_data = list(range(1, 101))  # 100条数据
    page_size = 10
    
    # 第1页
    print(f'第1页: {paginate(all_data, 1, page_size)}')
    # 第3页
    print(f'第3页: {paginate(all_data, 3, page_size)}')
    # 最后一页(可能不满一页)
    print(f'第10页: {paginate(all_data, 10, page_size)}')
    
    # 超出范围返回空列表(不会报错)
    print(f'第20页: {paginate(all_data, 20, page_size)}')  # []
    
    
    def paginate_with_info(items, page, page_size):
        """带分页信息的分页"""
        total = len(items)
        total_pages = (total + page_size - 1) // page_size
        page = max(1, min(page, total_pages))
    
        start = (page - 1) * page_size
        end = min(start + page_size, total)
    
        return {
            'items': items[start:end],
            'page': page,
            'page_size': page_size,
            'total': total,
            'total_pages': total_pages,
            'has_prev': page > 1,
            'has_next': page < total_pages,
        }
    
    info = paginate_with_info(all_data, 1, 10)
    print(f'第{info["page"]}页/共{info["total_pages"]}页')
    print(f'数据: {info["items"]}')
    print(f'有上一页: {info["has_prev"]}, 有下一页: {info["has_next"]}')
    

    5.2 文本处理和截断

    # 截断长文本,加省略号
    def truncate(text, max_length, ellipsis='...'):
        """用切片实现文本截断"""
        if len(text) <= max_length:
            return text
        return text[:max_length - len(ellipsis)] + ellipsis
    
    long_text = '这是一段很长的文本内容,我们需要将其截断显示'
    print(truncate(long_text, 15))  # 这是一段很长的文本内容,我...
    
    # 提取摘要(取前N个字符)
    def summary(text, n=100):
        return text[:n]
    
    # 取文本的最后N行
    def last_n_lines(text, n):
        lines = text.splitlines()
        return 'n'.join(lines[-n:])
    
    log = 'n'.join(f'第{i}行日志:一切正常' for i in range(1, 101))
    print(last_n_lines(log, 3))
    # 第98行日志:一切正常
    # 第99行日志:一切正常
    # 第100行日志:一切正常
    

    5.3 批量赋值模式

    # 初始化部分元素
    nums = [0] * 10
    # 将前5个设为1
    nums[:5] = [1] * 5
    print(nums)  # [1, 1, 1, 1, 1, 0, 0, 0, 0, 0]
    
    # 交替模式
    nums = [0] * 10
    nums[::2] = [1] * 5  # 偶数位为1
    print(nums)  # [1, 0, 1, 0, 1, 0, 1, 0, 1, 0]
    
    # 更复杂的模式——棋盘格
    size = 8
    row_template = [0] * size
    row_template[::2] = [1] * (size // 2)
    # row_template = [1, 0, 1, 0, 1, 0, 1, 0]
    
    board = []
    for i in range(size):
        if i % 2 == 0:
            board.append(row_template[:])
        else:
            board.append(row_template[::-1])
    
    for row in board:
        print(' '.join('█' if c else ' ' for c in row))
    

    5.4 螺旋遍历矩阵

    def spiral_order(matrix):
        """用切片实现矩阵的螺旋遍历"""
        result = []
        while matrix:
            # 取第一行
            result.extend(matrix[0])
            # 去掉第一行,然后逆时针旋转矩阵
            matrix = matrix[1:]
            if matrix:
                # 逆时针旋转 = 转置 + 行反转
                matrix = [list(row) for row in zip(*matrix)][::-1]
        return result
    
    matrix = [
        [1,  2,  3,  4],
        [5,  6,  7,  8],
        [9, 10, 11, 12],
    ]
    print(spiral_order(matrix))
    # [1, 2, 3, 4, 8, 12, 11, 10, 9, 5, 6, 7]
    

    六、切片对象——可复用的切片

    6.1 使用slice()创建切片对象

    # slice(start, stop, step)创建切片对象
    s = slice(2, 8, 2)
    print(s)  # slice(2, 8, 2)
    
    lst = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    print(lst[s])  # [2, 4, 6](和lst[2:8:2]完全一样)
    
    # 切片对象可以复用
    data1 = list(range(100))
    data2 = list(range(100, 200))
    data3 = list(range(200, 300))
    
    # 定义好切片规则,到处使用
    first_half = slice(None, 50)     # 等价于 [:50]
    last_quarter = slice(-25, None)  # 等价于 [-25:]
    every_10th = slice(None, None, 10)  # 等价于 [::10]
    
    print(data1[first_half])
    print(data2[last_quarter])
    print(data3[every_10th])
    

    6.2 切片对象的属性

    s = slice(2, 10, 3)
    print(s.start)  # 2
    print(s.stop)   # 10
    print(s.step)   # 3
    
    # indices()方法:根据序列长度规范化切片参数
    lst = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    print(s.indices(len(lst)))  # (2, 10, 3)
    # 这意味着实际提取的是索引2, 5, 8
    
    # 当切片参数超出范围时,indices()会自动修正
    s2 = slice(5, 100, 2)
    print(s2.indices(10))  # (5, 10, 2)(stop从100修正为10)
    
    s3 = slice(-100, 3, 1)
    print(s3.indices(10))  # (0, 3, 1)(start从-100修正为0)
    
    # 用indices()实现自己的安全切片操作
    def my_slice(sequence, slice_obj):
        """使用slice对象的通用安全切片"""
        start, stop, step = slice_obj.indices(len(sequence))
        result = []
        i = start
        if step > 0:
            while i < stop:
                result.append(sequence[i])
                i += step
        else:
            while i > stop:
                result.append(sequence[i])
                i += step
        return type(sequence)(result) if hasattr(type(sequence), '__call__') else result
    

    6.3 切片在自定义类中的应用

    class DataSeries:
        """自定义的数据库列——演示如何支持切片操作"""
    
        def __init__(self, data):
            self._data = list(data)
    
        def __getitem__(self, key):
            """支持索引和切片"""
            if isinstance(key, slice):
                # 可以用indices()规范化切片参数
                start, stop, step = key.indices(len(self._data))
                result = [self._data[i] for i in range(start, stop, step)]
                return DataSeries(result)
            elif isinstance(key, int):
                return self._data[key]
            else:
                raise TypeError(f'不支持的索引类型:{type(key)}')
    
        def __setitem__(self, key, value):
            """支持索引赋值和切片赋值"""
            if isinstance(key, slice):
                self._data[key] = value
            elif isinstance(key, int):
                self._data[key] = value
            else:
                raise TypeError(f'不支持的索引类型:{type(key)}')
    
        def __delitem__(self, key):
            """支持通过切片删除"""
            if isinstance(key, slice):
                del self._data[key]
            elif isinstance(key, int):
                del self._data[key]
    
        def __len__(self):
            return len(self._data)
    
        def __repr__(self):
            return f'DataSeries({self._data})'
    
    
    ds = DataSeries([10, 20, 30, 40, 50, 60, 70, 80, 90, 100])
    
    # 使用切片
    print(ds[2:5])       # DataSeries([30, 40, 50])
    print(ds[::2])       # DataSeries([10, 30, 50, 70, 90])
    print(ds[::-1])      # DataSeries([100, 90, 80, 70, 60, 50, 40, 30, 20, 10])
    
    # 切片赋值
    ds[2:5] = [300, 400, 500]
    print(ds)  # DataSeries([10, 20, 300, 400, 500, 60, 70, 80, 90, 100])
    
    # 切片删除
    del ds[3:7]
    print(ds)  # DataSeries([10, 20, 300, 70, 80, 90, 100])
    

    七、切片的性能与陷阱

    7.1 切片的内存消耗

    import sys
    
    # 切片总是创建新列表——对大列表会导致内存翻倍
    large_list = list(range(10000000))  # 1000万元素
    
    # 取一小段也会创建新列表(虽然只包含几个元素)
    small_slice = large_list[1000:1010]
    print(f'原列表大小: {sys.getsizeof(large_list):,} 字节')
    print(f'切片大小: {sys.getsizeof(small_slice):,} 字节')
    
    # 如果只需要遍历,不需要切片
    # 不推荐(创建新列表)
    for item in large_list[1000:1010]:
        print(item)
    
    # 推荐(用islice避免创建新列表)
    from itertools import islice
    for item in islice(large_list, 1000, 1010):
        print(item)
    

    7.2 切片的常见陷阱

    # 陷阱一:忘记切片是浅拷贝
    original = [[0]] * 5
    copy = original[:]
    copy[0][0] = 999
    print(original)  # [[999], [999], [999], [999], [999]](所有元素都变了!)
    print(copy)      # [[999], [999], [999], [999], [999]]
    
    # 陷阱二:对切片赋值 vs 对切片变量赋值
    lst = [1, 2, 3, 4, 5]
    s = lst[1:4]   # s是一个新列表
    s[0] = 100     # 修改s不影响lst
    print(lst)     # [1, 2, 3, 4, 5](lst没变)
    
    lst[1:4] = [100, 100, 100]  # 这是切片赋值,修改lst本身
    print(lst)     # [1, 100, 100, 100, 5]
    
    # 陷阱三:带步长的切片赋值长度必须匹配
    lst = [0, 1, 2, 3, 4, 5]
    # lst[::2] = [10, 20]  # ValueError(3个位置但只给了2个值)
    
    # 陷阱四:负数步长时start应大于stop
    lst = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    print(lst[2:8:2])   # [2, 4, 6](正确)
    print(lst[8:2:-2])  # [8, 6, 4](正确)
    print(lst[2:8:-2])  # [](空!start < stop,反向步长取不到值)
    
    # 陷阱五:给切片赋值的右边不一定是列表
    lst = [1, 2, 3, 4, 5]
    lst[1:4] = 'XYZ'  # 字符串被拆为字符序列
    print(lst)  # [1, 'X', 'Y', 'Z', 5]
    
    lst[1:4] = range(100, 103)  # range也是可迭代对象
    print(lst)  # [1, 100, 101, 102, 5]
    

    八、综合实战:用切片优雅解决实际问题

    8.1 回文判断

    def is_palindrome(s):
        """用切片判断回文"""
        # 去掉非字母数字字符,统一小写
        cleaned = ''.join(c.lower() for c in s if c.isalnum())
        return cleaned == cleaned[::-1]
    
    print(is_palindrome('A man, a plan, a canal: Panama'))  # True
    print(is_palindrome('race a car'))                      # False
    print(is_palindrome('上海自来水来自海上'))              # True
    

    8.2 杨辉三角

    def pascal_triangle(n):
        """生成杨辉三角——用切片轻松实现"""
        result = [[1]]
        for _ in range(1, n):
            prev = result[-1]
            # 核心:每行前后补0,相邻元素相加
            current = [1] + [prev[i] + prev[i + 1] for i in range(len(prev) - 1)] + [1]
            result.append(current)
        return result
    
    # 更Pythonic的写法(用切片)
    def pascal_triangle_v2(n):
        result = [[1]]
        for _ in range(1, n):
            prev = [0] + result[-1] + [0]
            current = [prev[i] + prev[i + 1] for i in range(len(prev) - 1)]
            result.append(current)
        return result
    
    for row in pascal_triangle_v2(8):
        print(' '.join(f'{x:3d}' for x in row).center(40))
    

    8.3 格式化输出对齐

    def format_columns(data, col_widths):
        """用切片分列展示数据"""
        result = []
        for row in data:
            formatted = [str(cell)[:w].ljust(w) for cell, w in zip(row, col_widths)]
            result.append(' | '.join(formatted))
        return 'n'.join(result)
    
    headers = ['姓名', '年龄', '城市', '职业']
    rows = [
        ['小明', 25, '北京', '软件工程师'],
        ['小红', 23, '上海', 'UI设计师'],
        ['Alexander Hamilton', 26, '广州', '数据科学家'],
    ]
    
    # 计算列宽
    col_widths = []
    for i in range(len(headers)):
        max_w = max(len(str(row[i])) for row in [headers] + rows)
        col_widths.append(max_w + 2)
    
    print(format_columns([headers] + rows, col_widths))
    

    九、本篇小结

    切片是Python中最强大、最常用的序列操作工具,值得好好消化:

    1. 完整语法:lst[start:stop:step],三个参数都可以省略,默认值根据step的正负确定
    2. 永不越界:切片访问永远不会报IndexError,越界自动截断——这是它和索引访问的关键区别
    3. 原地修改:lst[a:b] = values可以增删改列表元素,lst[a:a] = values在任意位置插入,lst[a:b] = []删除一段
    4. 浅拷贝:lst[:]创建新列表,但内层对象共享(嵌套列表要注意)
    5. 切片对象:slice(start, stop, step)可复用切片规则,.indices(len)规范化参数
    6. 带步长的切片赋值:右边长度必须和切片结果长度一致

    切片操作是Python编程中的“基本功”,但用好了就是“杀手锏”。熟练运用切片,能让代码减少一半的循环和条件判断。下一篇将进入列表的增删改查方法详解——从增加元素的四大方式开始。

    本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
    作者最新文章
    编程开发 Python
    相关文章 更多
    精品专题 更多
    装机必备

    正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

    Windows

    正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

    PDF教程

    正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

    macOS软件

    正软商城macOS软件专区,精选适用于Mac电脑的办公、设计、影音、效率、开发和系统工具,提供软件功能介绍、macOS兼容版本、正版授权及购买下载服务。

    IOS软件

    正软商城iOS软件专区,精选适用于iPhone和iPad的办公、学习、影音、设计、效率及AI应用,提供功能介绍、适用设备、系统要求和正版获取方式等信息。

    AI

    正软商城AI软件专区,汇集AI写作、AI绘画、AI视频、AI办公、AI编程、AI翻译、智能客服和数据分析等人工智能工具,提供功能介绍、适用平台、收费方式及正版购买信息。

    Mac软件 更多
    Postman macOS版
    Postman macOS版

    Postman是一套面向API全生命周期的开发与测试平台,可在Mac上发送和调试多种协议请求,管理集合、环境及认证信息,并完成脚本测试、模拟服务、监控、文档发布和团队协作。它适合开发、测试及运维人员使用,提供个人免费方案。

    Docker Desktop macOS版
    Docker Desktop macOS版

    Docker Desktop 是 Docker 官方为 Mac 提供的容器开发环境,集成 Docker Engine、命令行工具、Compose、Build、Kubernetes 与图形化管理界面。

    Android Studio macOS版
    Android Studio macOS版

    Android Studio 是 Google 面向安卓应用开发提供的官方集成开发环境,基于 IntelliJ IDEA 构建。它整合智能代码编辑、Gradle 构建、界面预览、设备模拟、性能分析、调试测试及 APK 分析等工具。

    Xcode macOS版
    Xcode macOS版

    Xcode 是苹果面向 Mac 提供的官方集成开发环境,将代码编辑、项目构建、SwiftUI 实时预览、设备模拟、自动化测试、断点调试、性能分析和应用分发整合在同一套工作流中,适合开发与维护 iPhone、iPad、Mac、Apple Wa

    JetBrains WebStorm macOS版
    JetBrains WebStorm macOS版

    JetBrains WebStorm 是面向 JavaScript、TypeScript 和现代 Web 技术的专业集成开发环境,可智能理解项目结构,提供代码补全、重构、错误检查、运行调试、测试及 Git 工具。

    PhpStorm macOS版
    PhpStorm macOS版

    PhpStorm 是 JetBrains 推出的专业 PHP 集成开发环境,可在 Mac 上完成代码编写、智能检查、重构、调试、测试和数据库管理。它支持主流 PHP 框架、Composer、Git、Docker 与远程解释器。

    JetBrains PyCharm macOS版
    JetBrains PyCharm macOS版

    JetBrains PyCharm 是面向 Python 开发者的集成开发环境,提供智能补全、代码检查、重构、调试、测试、版本控制及虚拟环境管理功能。Mac 版兼容 Intel 与 Apple 芯片,核心功能可免费使用。

    JetBrains IntelliJ IDEA macOS版
    JetBrains IntelliJ IDEA macOS版

    IntelliJ IDEA 是 JetBrains 推出的专业集成开发环境,重点服务于 Java、Kotlin 与 JVM 项目开发。软件集成代码补全、静态检查、重构、调试、测试、版本控制及构建工具,并可借助插件扩展语言和框架支持。

    Visual Studio Code macOS版
    Visual Studio Code macOS版

    Visual Studio Code 是微软提供的免费代码编辑器,支持 macOS,并为 Intel 与 Apple 芯片 Mac 提供适配版本。软件集代码编辑、调试、Git 源代码管理、集成终端和扩展市场于一体。

    REAPER macOS版
    REAPER macOS版

    REAPER是Cockos开发的数字音频工作站,提供多轨音频与MIDI录制、剪辑、处理、混音和母带制作工具。Mac版兼容Intel与Apple芯片,支持AU、VST、VST3、CLAP等插件格式,并提供高度可定制的工作流程。

    Adobe Audition macOS版
    Adobe Audition macOS版

    Adobe Audition 是面向播客、影视后期、音乐制作及内容创作者的专业音频工作站,提供波形精修、多轨录制与混音、频谱编辑、降噪修复、响度匹配和效果处理工具,并可与 Adobe Premiere 协同完成视频声音制作。

    Pro Tools macOS版
    Pro Tools macOS版

    Pro Tools 是 Avid 推出的专业数字音频工作站,覆盖多轨录音、无损剪辑、MIDI 编曲、插件处理、自动化混音及声音与画面同步等工作。它拥有 Intro、Artist、Studio 和 Ultimate 等方案。

    WINDOWS 更多
    PixPix 网页版
    PixPix 网页版

    PixPix 是面向品牌、卖家和内容团队的在线 AI 图片视频创作平台,提供图视频 Agent、无限画布、图片生成、视频生成、自然语言编辑及商品套图、产品精修和带货视频等电商工具。

    Postman Windows版
    Postman Windows版

    Postman 是面向 API 全生命周期的开发与协作平台。Windows 桌面版可用于构建和发送 HTTP、GraphQL、gRPC、WebSocket、MQTT 等请求,并提供环境变量、集合、脚本测试、模拟服务、监控、文档及团队工作区等

    Docker Desktop Windows版
    Docker Desktop Windows版

    Docker Desktop 为 Windows 开发者提供集成式容器环境,内置 Docker Engine、命令行工具、Compose、Build 与 Kubernetes 等组件,可在本机完成镜像构建、容器运行、日志查看和资源管理。

    Android Studio Windows版
    Android Studio Windows版

    Android Studio 是 Google 面向 Android 应用开发提供的官方集成开发环境,以 IntelliJ IDEA 为基础,集成智能代码编辑、Gradle 构建、设备模拟、界面预览、调试测试及性能分析工具,

    JetBrains WebStorm Windows版
    JetBrains WebStorm Windows版

    WebStorm 是 JetBrains 面向 JavaScript、TypeScript 和现代 Web 技术打造的集成开发环境。它提供项目级代码分析、智能补全、安全重构、导航搜索,并集成调试、测试、终端、Git 与常用前端工具,

    JetBrains PhpStorm Windows版
    JetBrains PhpStorm Windows版

    PhpStorm 是 JetBrains 面向 PHP 与现代 Web 开发打造的专业集成开发环境,提供代码补全、静态检查、重构、调试、测试、数据库、版本控制及前端语言支持。Windows 用户可直接下载安装程序,

    JetBrains PyCharm Windows版
    JetBrains PyCharm Windows版

    PyCharm 是 JetBrains 推出的 Python 集成开发环境,提供智能代码补全、错误检查、重构、调试、测试、Git、终端及 Jupyter Notebook 支持。统一版安装后可体验 30 天 Pro 功能,

    JetBrains IntelliJ IDEA Windows版
    JetBrains IntelliJ IDEA Windows版

    JetBrains IntelliJ IDEA 是以 Java、Kotlin 和 JVM 项目为核心的专业集成开发环境,提供智能补全、代码检查、安全重构、调试、测试、版本控制及构建工具集成。统一发行版的核心功能可免费用于商业和非商业项目,

    Visual Studio Code Windows版
    Visual Studio Code Windows版

    Visual Studio Code 是微软推出的免费代码编辑器,Windows 版集成智能补全、代码导航、调试、终端和版本控制,并可通过扩展添加语言、格式化及远程开发能力。它启动较快、配置灵活,

    REAPER Windows版
    REAPER Windows版

    REAPER 是 Cockos 推出的数字音频工作站,适用于录音、MIDI 编曲、音频编辑、混音、母带制作及声音设计。软件安装包小巧,支持多轨录制、灵活路由、自动化、第三方插件和脚本扩展,并提供完整功能的 60 天免费评估期。

    Adobe Audition Windows版
    Adobe Audition Windows版

    Adobe Audition 是面向播客、影视后期、广播与音乐制作的专业音频工作站,提供波形编辑、多轨混音、频谱分析、录音、降噪修复和效果处理等功能。Windows 版通过 Adobe Creative Cloud 安装和管理,

    Pro Tools Windows版
    Pro Tools Windows版

    Pro Tools 是 Avid 推出的专业数字音频工作站,提供多轨录音、音频剪辑、MIDI编曲、插件处理、自动化混音及影视声音制作能力。它适合音乐人、录音师、制作人和音频后期团队使用,并提供免费入门版、订阅方案及永久授权选择。