简介:Python从入门到精通系列第5章《列表与元组》精品课件PPT,面向Python初学者、高校学生及教师备课场景;课件以序列数据结构为主线,系统讲解列表的创建与删除、索引访问、切片、for循环遍历、enumerate()函数、元素添加/修改/删除,以及统计计算、sort()和sorted()排序、列表推导式,并对比元组的不可变特性与打包/解包应用。二维列表的嵌套循环示例一并给出,方便理解矩阵与表格数据处理;全课共30页,知识点分级清晰、代码示例覆盖主要操作,适合课堂演示、课后复习或自学预习,也可作为教学课件二次加工基础。交付内容为1个PPT文件,压缩包整体约873KB,轻巧便于下载分享,目前已有620人学习/浏览。结合知识讲解与代码示例,能帮助读者系统掌握列表和元组这两类核心数据结构,提升实际编程中的数据组织与代码可读性。
1. 列表与元组:Python入门的“万能工具箱”
学Python绕不开列表(list)和元组(tuple)。我在带新人或者写教程的时候,经常把这两个数据结构比作“装东西的抽屉”:列表是那种可以随时塞东西、抽出来换位置的开放抽屉,元组则是出厂时封好、不能随便改动的密封箱。你要做爬虫抓数据、写量化策略、处理Excel表格,甚至只是写个脚本批量改文件名,列表和元组都是躲不开的基本功。
这一章课件我从“为什么需要它们”讲起,而不是直接丢出一堆方法名让你背。列表和元组的本质区别,一句话就能说清:列表是可变的(mutable),元组是不可变的(immutable)。别小看这六个字,它决定了你能对数据做什么、不能做什么,也决定了程序在内存里怎么存放这些数据。
标题里写“从入门到精通”,内容也确实覆盖了从定义、索引、切片到嵌套、推导式、元组拆包这些核心操作,还配了30页PPT常用的对比表、操作题和思考题。这篇文章我会把这一章的脉络重新捋一遍,把我自己在教学和实战中反复强调的重点拎出来,补上PPT里没写但要命的细节,最后给你一套可以直接抄作业的实操脚本。
适合谁来读?刚学完变量和if/for、准备啃数据结构的新手,或者已经会用列表但总在切片边界、深浅拷贝上翻车的老手,都能从这里找到点东西。
2. 列表操作的核心细节:从切片到嵌套的实战要点
2.1 切片别死记,记住“左闭右开”就够了
列表切片是出现频率最高的操作之一,也是新手最容易懵的地方。lst[a:b]取的是从下标a开始、到下标b之前(不包含b)的元素。这个设计叫“左闭右开”,刚开始会觉得别扭,但用久了你会发现它特别顺手:lst[0:3]正好取前三个元素,lst[:3]取前三个,lst[3:]从第三个一直取到末尾,三个切片正好把列表切分成三块,不重不漏。
我自己教学生的时候,会让他们先背这个口诀:“切片写两个数,左边含右边不含,省略左边从头开始,省略右边到尾结束。”接着再补一个容易被忽略的操作:负数索引。lst[-1]是最后一个元素,lst[-3:]是最后三个元素。这个在处理日志文件、时间序列数据的时候特别常用——你想拿最近三条记录,直接切片就行,不用先算长度。
另一个实战点是把切片用在赋值上。很多人不知道,切片可以整体替换一段元素:lst[1:3] = [100, 200, 300]不仅把1、2号位换掉,还会自动把3号位的元素插进来。这个特性在批量修改数据时非常高效,比一个个赋值少写好几行。
2.2 增删改查:方法选不对,代码丑十倍
列表的基本操作,PPT里通常列成一张表:append、insert、remove、pop、index、count、sort、reverse。这张表不难,但我想展开说说“什么时候选哪个”。
- 尾部添加用append,这几乎是唯一选择。如果你用
insert(0, x)往头部加,每次都会把后面所有元素往后挪一位,数据量一大(比如上万条),慢得肉眼可见。 - 删除元素要先想清楚按值删还是按下标删。按值删用
remove(x),注意它只删第一次出现的那个;按下标删用pop(i),而且pop会返回被删的值——这个返回值经常被忽略,其实在做“取出并移除”的操作(比如队列)时特别好用。如果只想清空列表,用clear(),不要用lst = [],后者是换了个新列表,前者是原地清空,前者更快且不影响外面引用它的变量。 - 查找下标用index,但注意如果值不存在会抛ValueError。实战里我习惯先判断
if x in lst再index,或者直接用try/except包一层。
排序这里有个常见的坑:lst.sort()是原地排序、返回None,而sorted(lst)是生成新列表、不改原列表。很多新手在交互环境里写出lst = lst.sort(),结果lst变成了None,一脸懵。记住:排序要结果、不变原数据用sorted;不在乎原数据、想省内存用sort。
2.3 嵌套列表:二维数据的底层逻辑
列表里面套列表,就是二维结构,比如成绩表:scores = [["张三", 85, 92], ["李四", 78, 88]]。访问张三的数学成绩就是scores[0][1]。这个嵌套结构是后面学pandas、numpy之前最直观的“表格”模型。
嵌套列表还有一个高频需求:转成字典。搜索热词里也有“两个列表转字典”,这个需求在数据处理时天天见——一个列表是字段名,另一个是值。最优雅的写法是用zip:dict(zip(keys, values))。zip把两个列表按位置配对成元组,dict再把元组列表变成字典,一行搞定。但如果两个列表长度不一致,zip会按短的来,这个要心里有数。
2.4 列表推导式:写一行顶三行,但别装过头
列表推导式是Python最漂亮的语法之一。[x * 2 for x in range(10) if x % 2 == 0],读起来像英文句子:对range(10)里的每个x,如果x是偶数,就把它乘2放进新列表。它比传统for循环快,因为底层是C语言级别的迭代,而且代码短、可读性高。
但我要说一句泼冷水的话:推导式不要嵌套超过两层。[(x, y) for x in range(5) for y in range(5)]勉强能看,三层以上基本就是考验读者的耐心了。碰到复杂逻辑,老老实实用普通for循环,代码的可维护性比“看起来很厉害”重要得多。
3. 元组的不可变性:为什么需要“只读”的数据结构
3.1 不可变到底意味着什么
元组用圆括号:t = (1, 2, 3)。它的核心特性是创建之后不能修改——不能append、不能remove、不能给某个位置赋值。这不是Python故意限制你,而是有实际考量的:
第一,元组可以作为字典的键。字典的键要求是“可哈希的”(hashable),而可哈希的前提就是不可变。列表是可变类型,所以{lst: "value"}直接报TypeError;但{(1, 2): "坐标点"}完全合法。写地图应用、用坐标做索引的时候,这个特性特别好用。
第二,元组更省内存。我做过一个简单测试:同样装一百万个整数,元组占的内存比列表少大约20%。原因是列表为了支持动态扩容,会预留额外空间;元组长度固定,不需要这些余量。数据量大的时候,这个差异不是小数目。
第三,元组更安全。如果你的数据代表的是固定配置、常量集合、函数返回的多个值,用元组能防止程序在某个角落意外改动数据。这在多人协作的项目里尤其重要——别人看到元组就知道“这里不该改”,这是一种代码层面的契约。
3.2 元组拆包:Python最优雅的赋值方式
元组拆包(unpacking)是我最爱讲的知识点。a, b = (1, 2)这行代码,在别的语言里得写成两三行,Python里一行搞定。更妙的是,交换两个变量:a, b = b, a——这在C或Java里需要临时变量,在Python里直接写。
拆包还能用在循环里:for name, score in student_list:,如果student_list里每个元素是二元元组,这个写法会直接帮你拆成两个变量,代码既清晰又省事。还有带星号拆包:first, *rest = [1, 2, 3, 4, 5],first拿到1,rest拿到剩下的[2,3,4,5]。处理“第一个元素特殊、其余统一处理”的场景时,这个语法能省好几行代码。
3.3 元组里的“假不可变”:元素本身可变怎么办
这里有个特别容易踩的坑:元组不可变是指元组的元素指向不能变,但如果某个元素本身是可变对象(比如列表),这个列表里面的内容是可以改的。
t = (1, 2, [3, 4]) t[2].append(5) # 不报错!t 变成了 (1, 2, [3, 4, 5])很多新手在这里懵了:元组不是不能改吗?对啊,元组里第二个元素仍然指向那个列表,只是列表自己变长了。理解这个需要分清楚“引用”和“对象”的区别。这个知识点也是面试中常考的“坑题”,PPT里如果没讲清楚,我这里补上。如果想让元组真正完全不可变,里面所有的元素也必须是不可变类型,这就是为什么纯数字、字符串元组才是“最安全”的元组。
3.4 具名元组namedtuple:让数据自带字段名
搜索热词里没有直接出现,但我在讲完元组后一定会补这个进阶内容:namedtuple。它来自collections模块,用起来像元组一样不可变,但你访问元素的时候不用t[0],而是可以直接t.name、t.age。
from collections import namedtuple Person = namedtuple("Person", ["name", "age"]) p = Person("张三", 25) print(p.name) # 张三这个在写爬虫保存一条记录、读配置文件的每一项、传临时数据结构的时候,比用字典写起来短,比用普通元组可读性强很多。我觉得它是“元组进阶”里性价比最高的知识点。
4. 实操演练:用列表与元组完成一个学生成绩管理小系统
4.1 需求设计
光看不练等于白学。我在讲完基础知识后,总会让学生做一个完整的小项目:学生成绩管理小系统。要求很小,就三个功能:
- 能输入若干条学生成绩,每条包含姓名和语文、数学两科分数;
- 能计算每个人的平均分,并按平均分从高到低输出;
- 能输出数学成绩最高的学生姓名。
这个小系统用不到文件操作和函数,只用列表、元组、循环、排序就能完成,非常适合检验这一章的学习效果。
4.2 代码实现与逐行讲解
# 第一步:用列表存所有学生,每个学生用元组表示 students = [] n = int(input("请输入学生人数:")) for i in range(n): name = input("请输入姓名:") chinese = float(input("请输入语文成绩:")) math = float(input("请输入数学成绩:")) students.append((name, chinese, math)) # 用元组保证一条记录不被意外修改 # 第二步:计算平均分并排序 # 先给每个学生加上平均分,变成一个三元元组的新列表 with_avg = [] for stu in students: avg = (stu[1] + stu[2]) / 2 with_avg.append((stu[0], stu[1], stu[2], avg)) # 按平均分降序排序:key参数传入一个“取排序依据”的函数 with_avg.sort(key=lambda x: x[3], reverse=True) # 输出结果 print("排名:") for name, chinese, math, avg in with_avg: # 元组拆包,直接拿四个变量 print(f"{name}:语文 {chinese},数学 {math},平均分 {avg:.1f}") # 第三步:找数学最高分学生 # max函数搭配key参数,这里的意思是“根据数学成绩这一项取最大值” top_math_student = max(students, key=lambda x: x[2]) print(f"数学最高分:{top_math_student[0]},{top_math_student[2]}分")这段代码里,我用元组存每一条学生记录,主要目的是防止程序运行过程中不小心把某条成绩改掉;用列表存所有记录,是为了方便排序和增删。这个“外层用列表、内层用元组”的组合,在真实项目里也非常常见——比如爬虫抓下来的数据,每条记录固定不动,用元组;抓了很多条,用列表。在学习这个阶段,你要刻意去体会这个组合的用意,而不是只把代码抄一遍。
4.3 项目运行效果与易错点提示
运行一下这个程序:
请输入学生人数:3 请输入姓名:张三 请输入语文成绩:90 请输入数学成绩:80 请输入姓名:李四 请输入语文成绩:85 请输入数学成绩:95 请输入姓名:王五 请输入语文成绩:70 请输入数学成绩:88 排名: 李四:语文 85.0,数学 95.0,平均分 90.0 张三:语文 90.0,数学 80.0,平均分 85.0 王五:语文 70.0,数学 88.0,平均分 79.0 数学最高分:李四,95.0分学生在做这个项目时,常见错误有三个:一个是students.append((name, chinese, math))写成了students.append(name, chinese, math),少了括号,把三个独立参数传给append导致报错;一个是排序时忘了reverse=True,结果排成了升序;还有一个是在max的key参数里写成了lambda x: stu[2],少了个x导致所有学生都用同一个值比较,结果返回第一个学生,逻辑上“刚好错”。这三个错误都很经典,遇到的时候别急着改,先自己定位问题,这才是真正的提高。
5. 常见问题与避坑经验汇总
我把平时被问得最多的问题整理成一张速查表,方便你收藏:
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 列表赋值后,修改新列表原列表也变了 | 变量存的是引用,b = a只是让b指向同一块内存 | 用b = a[:]或b = a.copy()做浅拷贝 |
| 二维列表做拷贝后,改内层还是互相影响 | 浅拷贝只复制外层,内层仍是同一个列表 | 用copy.deepcopy()做深拷贝 |
| 对元组执行append报错 | 元组不可变 | 换成列表,或重新创建元组t + (4,) |
| 切片取不到最后一个元素 | 左闭右开规则 | 省略结尾下标,如lst[1:] |
| sort和sorted用混 | 一个是原地排序返回None,一个返回新列表 | 要结果用sorted,不Care原对象用sort |
| 列表推导式里条件写错位置 | if用在for前面是表达式,用在后面是过滤 | 过滤条件放后面;转换表达式放前面 |
5.1 深浅拷贝是列表最大的暗坑
这个问题几乎每个学列表的人都会遇到。看下面这段代码:
a = [1, 2, 3] b = a # 这不是拷贝,只是多了一个名字 b.append(4) print(a) # [1, 2, 3, 4],a也被改了!如果不理解“变量存的是引用”,这段代码会让你怀疑人生。Python的变量不像C那样存的是值本身,而是存了一个“指向对象的指针”。b = a的意思不是复制列表,而是让b也指向a指向的那块内存。所以改b等于改a。
正确的拷贝方式是b = a[:]或者b = list(a),这会生成一个新的列表对象。但这里还有一个升级版的坑:如果列表里嵌套了列表(二维列表),浅拷贝只是复制外层,内层还是共用的。
a = [[1, 2], [3, 4]] b = a[:] # 浅拷贝 b[0].append(99) print(a) # [[1, 2, 99], [3, 4]],内层还是改了要彻底隔离,得用copy.deepcopy(a)。我自己在实际开发里,如果只是操作一维列表,浅拷贝就够了;但处理嵌套结构(比如把一份配置模板复制多份),一定用深拷贝,否则一改全改,排查特别痛苦。
5.2 元组被误认为“不能改”的四个边界场景
讲元组不可变的时候,有几个边界场景容易引发误解,我总结成四条,每一条都是踩过坑换来的:
- 元组里的元素是列表,列表内容可以改,元组引用不变。这在前面已经讲过。
t = (1)和t = (1,)不一样。前者t是整数1,后者才是元组。定义单元素元组时,那个逗号不能省。- 元组和列表可以相互转换:
tuple([1,2,3])得到元组,list((1,2,3))得到列表。这个操作本身就是O(n)的,数据量大时要注意性能。 - 字符串是不可变序列,它和元组共享很多行为:支持索引、切片、
in判断、for遍历。理解了元组的不可变特性,也就理解了为什么字符串拼接是低效的——每次都生成新字符串。
5.3 用conda管理虚拟环境时列表命令的两个实用细节
搜热搜词的时候看到“anaconda虚拟环境列表”这个关键词,顺便说一嘴。很多人在多个Python项目之间切换环境,常用的命令是conda env list,它会列出所有虚拟环境以及对应的路径。还有一个是conda list,这个列的是当前环境里安装的Python包。
这两个命令名字很像,但作用完全不同,我把它们搞混过好几次。现在我的习惯是:先conda env list确认自己在哪个环境,再conda list看包列表。另外,装包的时候一定先确认当前环境名,不然很容易把包装到base环境里,时间一长,环境之间依赖全乱了。
6. 这套知识还能怎么用:从课件延伸到真实项目
学完列表和元组,最直接的反馈就是“我能拿它干点什么”。我在这里给你几个方向,这些方向都是我实际带项目时用得上的场景,比单纯做题有成就感得多。
方向一:爬虫数据清洗。抓下来的网页内容往往是一大段文本,你要用正则或XPath提取出关键字段,存成一个个元组(标题、链接、时间),再放进列表统一处理。这里就用到“外层列表、内层元组”的模式,配合切片取最近N条,再配合排序按时间倒序。
方向二:量化交易策略里的行情数据。每一根K线可以用元组表示(时间、开、高、低、收、成交量),整个行情就是元组的列表。计算移动平均线时,就是对收盘价这个字段做列表切片取窗口——closes[i-5:i]就是最近5根K线的收盘价。做回测的时候,为了性能,常用numpy的数组,但底层逻辑和列表切片完全一致。
方向三:办公自动化。读写Excel时,openpyxl库经常会把一行数据读成一个元组,多行就是元组的列表。处理成绩表、工资表、库存表,本质上就是列表的排序、筛选、拼接操作。理解了列表,你就理解了Excel数据在Python世界里的基本形态。
方向四:LeetCode刷题。列表和元组是算法题的基础载体。两数之和、合并两个有序数组、旋转数组,全都是列表操作。元组相关的题相对少,但拆包思想在很多字符串处理题目中会用到。
7. 最后再说几句掏心窝的话
我教这门课教了很多遍,每次讲列表和元组这一章,都会想起自己当年学Python的拧巴——明明看起来就是个数组,怎么还有这么多讲究?等你真正写过几万行代码,回头再看这一章,你会发现PPT上那一页“列表常用方法表”其实是整个数据处理领域的微缩模型:增删改查是所有数据操作的雏形,可变与不可变的思考方式影响着你对一切数据模型的理解。
实操这块,我强烈建议你把这篇文章里的成绩管理小系统亲手敲一遍,再自己加两个功能:按语文成绩筛选出及格的人;计算全班数学平均分。做完之后,再试着把学生记录从元组改成列表,看看代码哪里会“如履薄冰”——你会发现用元组其实是一种提前规避风险的设计,而不是语法上的束缚。
数据结构和生活一样,可变的东西灵活却容易失控,不可变的东西僵硬但足够安全。列表和元组放在一起用,恰好是“灵活与安全的平衡”,这也是Python这门语言的设计哲学之一。把这章吃透,后面学字典、集合,你会发现很多套路都是通的。
本文还有配套的精品资源,点击获取