资讯详情 Python期末复习全攻略:语法体检与易错点详解
📅 2026/10/24 13:38:59
简介面向K12阶段Python初学者的期末复习要点文档以清晰条目梳理期末高频考点包含输入输出、字符串排序去重、列表逆序与去重、自定义sort排序、桶排序、二分查找、模块化设计、异常处理及面向对象核心概念可作为考前快速回顾与查漏补缺的随身清单。资源包为单个docx格式文档约865KB共1个文件适合打印或电脑阅读内容紧凑无需额外解压繁琐操作该资料上线后已有439人学习适合正在备战Python期末考试的K12学生及入门爱好者。除了系统归纳基础语法还额外整理了一系列易错点与典型代码示例例如list.sort()原地排序返回None、浅拷贝与深拷贝区别、集合升序去重特性等能帮助理解本质并降低考试踩坑概率整体覆盖选择、填空与编程题常考角度是一份能直接对照练习的实用复习资料。1. Python 期末复习到底在复习什么一场给 K12 新手的“语法体检”K12 阶段的 Python 期末复习最怕的不是题目难而是很多同学把 Python 当黑匣子——代码看着熟一运行就翻车。期末考的本质其实是给这段学习做一次“语法体检”数据怎么进、存进哪种容器、最后怎么出每一步都有固定规则。用收拾书包来打比方input() 是往书包里塞东西列表和字典是不同隔层print() 是把书拿出来展示。如果“进、存、出”这条主线没理顺后面所有代码都会跟着歪。这篇文章不谈玄学专门把期末常考的概念掰开揉碎帮你建立一眼看穿的认知。2. 输入输出这条主线期末卷上的“分数搬运工”2.1 连续输入一行代码背后的三个小机关先记住一句话input() 永远只负责“读一整行字符串”它不关心你输入的是几个数。K12 题目里经常出现“一行给三个整数”“一行给若干名字”如果你老实写三行 input()代码又臭又长还容易漏读。所以卷子上高频出现这种写法a, b, c map(int, input().split())这段代码能拆成三个小机关input()读进来的是字符串例如1 2 3.split()默认按空格把字符串切成列表得到[1, 2, 3]map(int, 列表)把每个字符串转成整数再依次赋给 a、b、c。很多同学误以为 input() 能直接返回“三个数”其实它返回的是一整行文本。split() 像一把餐刀把一串文字从空格处切开map() 像一台翻译器把切好的文字翻译成目标类型。如果直接用A, B input().split()得到的是两个字符串而不是数字。题目说要整数时忘了 map后面做加法就会得到字符串拼接而不是数值求和。那么什么时候用split(,)看输入分隔符。输入A同学,B同学,C同学就必须写成.split(,)否则切不开。所以复习时要主动问自己我读的是空格分隔还是逗号分隔这是每年都有不少人踩的坑。更进一步如果题目要在一行里读“一整列数字”可以用num_list list(map(int, input().split()))这行代码的意思是把分解、转换后的结果装进一个列表作为后续排序、统计的原料。可以说input().split().map()是期末输入题的标准三件套背住它的执行顺序就能看懂一切像天书一样的读入代码。2.2 print 不是“一键输出”五个参数决定它怎么干活print 是每个 Python 新手学的第一个函数但期末考根本不考“print 能打印什么”而是考“print 到底按什么规则打印”。完整格式是print(*objects, sep , end\n, filesys.stdout, flushFalse)参数逐个说objects要输出的对象可以放多个用逗号隔开sep多个对象之间的分隔符默认空格end整个输出以什么结尾默认换行file输出到哪里默认屏幕flush是否立即刷新缓冲区默认 False。看了这个签名很多“诡异输出”就解释得通了。比如你想输出“A同学的编号-2024”且结尾不换行print(A同学, 2024, sep-, end!)输出就是A同学-2024!。如果 sep 不写默认会变成“A同学 2024”如果 end 不写末尾会多一个换行。考试里经常让你判断“这段代码到底输出几行”本质就是在考 end 参数会不会吞掉换行。file 参数也很直观默认是屏幕但要写到文件可以传一个文件对象。flush 平时很少改但在需要实时看到进度的时候会设为 True。复习时不用死记只要知道 print 是一个带旋钮的水龙头sep 控制对象之间隔多远end 控制最后一滴水落在哪file 控制水流到哪个池子。2.3 ifname main一段代码的“主角开关”项目正文里有一条复习点if __name__ __main__是为了保证代码的可重用性。这句话不好懂我们换个说法每个 .py 文件都有两种身份。当你直接运行它时它是主角当另一个文件 import 它时它是配角。__name__是 Python 自动放好的身份牌主角牌子上写__main__配角牌子上写文件名。# helper.py def hello(): print(你好) if __name__ __main__: hello()直接运行python helper.py会打印“你好”在另一个文件里import helper什么也不会打印只有调用helper.hello()才打印。为什么要有这个开关因为很多 .py 文件既能自己跑也要能被别人调用。如果 import 时把自己的测试代码也执行一遍别人还没用就莫名其妙输出一堆东西那“可重用”就无从谈起。期末选择题爱这么出有两个 .py 文件一个 import 另一个问运行后会输出什么。如果你记得“主角开关”一眼就能看出被 import 的文件不是主角它只在判断外面执行 import 级别的代码。所以把“可复用的函数定义”放在判断外面把“只想自己运行时看的测试调用”放在判断里面就不会翻车。3. 列表、元组、字典、集合怎么选容器才不会翻车3.1 可变与不可变先看“能不能原地改”Python 的数据类型很多K12 期末最常挑“可变不可变”来考。一句话定义列表、字典、集合是可变类型数值、字符串、元组是不可变类型。打个比方可变类型像一个能随时加隔层、拆隔层的收纳箱你可以往里面塞东西、取出来、换位置不可变类型像一个刻好的印章印章上的字一旦刻好就不能改想换字只能重新刻一个。字符串看起来能改其实每一次拼接和替换都是重新生成一个新字符串原来的字符串始终没动。为什么这个区分那么重要因为它决定哪些操作可以原地完成哪些必须换新对象。列表支持 append、pop、del元组没有这些方法只能整体重新生成。同样是“修改”列表是“在同一个盒子里捣鼓”元组是“换一个盒子”。这里有个非常经典的单元素元组考点A (3) # 整数 3 B (3,) # 元组只有一个元素 3区别就在一个逗号。Python 识别元组靠的是逗号不是括号。A (3)只是加了括号的整数B (3,)才是元组。题目问“A 的数据类型”好多人看到括号就写 tuple结果丢了分。另外元组访问速度比列表快一点。如果题目只要求遍历不要求修改用元组更稳。这也是元组存在的意义之一不打算改的数据就用一个没法改的容器装着反而省心和安全。3.2 列表的“身份”与“复制”同一个对象还是另一个对象很多同学认为“列表赋值就是在复制内容”这是期末复习里最危险的错觉。来看两段代码x [1, 2, 3] y x # 没有复制只是给同一个列表起了小名 z x[:] # 切片创建新列表y 和 x 指向同一个列表对象id 相同z 是新建的对象id 与 x 不同。因为 y 和 x 是同一个对象所以y.append(4)之后x 也变成 [1, 2, 3, 4]而 z 怎么修改都不影响 x。究其原因y x只是把“x 的地址”复制给了 y而不是把列表内容重新复制了一份。列表的切片属于浅复制。为什么叫“浅”因为它只复制第一层。如果列表里装的是整数这类不可变元素浅复制就足够如果列表里还套着列表浅复制不会去复制内层列表内层仍然共享。期末考试一般不往深了考但你要能说出“浅复制”三个字才能在判断题里分清“会改到原列表”和“不会改到原列表”。如果需要删元素del x[0]删除第一个元素del x删除整个列表pop()不带参数默认删最后一个pop(i)按下标删。这些都是列表“可变”的具体表现。复习时多问一句这个操作是原地改还是返回新东西原地改的通常返回 None。3.3 集合与字典去重很方便但规则也多集合和字典都用花括号看起来像亲戚用途完全不同。集合的核心卖点是自动去重和自动升序。把一串输入丢进 set重复值自动消失。不过集合有三大限制不支持下标访问不能 del 部分元素元素必须是不可变类型。所以集合里可以放元组不能放列表。原因很简单集合的底层逻辑是“让元素按规则互不重复”如果元素本身可变它的身份会变来变去集合的规则就乱了。字典则是“键到值”的映射结构。键不能重复值可以重复键必须是不可变类型字符串、元组都能当键列表不能当键。字典不支持双向索引你可以用键查值但不能拿值反查键。想遍历字典用keys()拿键列表values()拿值列表items()拿键值对列表。为什么需要这三种方法因为“字典没有下标”想要什么就先拿到对应的“名单”。一个很实用的去重组合是“字符串转集合再拼回字符串”s1 list(set(input())) s1.sort() print(.join(s1))它先把字符串拆成字符用 set 去重转回列表排序最后用空字符串拼回去。题目要求“输出去重后按编码排序的字符串”时这是标准答案。注意集合虽然自动升序但“自动顺序”不是编程接口不能依赖它输出。要保留“第一次出现顺序”得用另一招这一招我们放到排序章重点讲。4. 排序与去重考卷上最容易翻车的三件事4.1 sort、sorted、reverse、reversed改不改原列表是分界线先说结论list.sort()是原地排序没有返回值sorted(list)返回新列表不碰原列表。这两者的区别是 K12 期考排序题的第一考点。a [3, 1, 2] b a.sort() print(b) # None print(a) # [1, 2, 3]很多新手第一次写b a.sort()时特别自然以为 b 会得到排好序的列表结果 print(b) 输出 None。为什么因为 sort 方法把结果“留在了自己身上”不会交还给左边的变量。用大白话说它是“就地整理房间”整理完不会给你拍一张新照片。想拿到新列表就用 sortedc [3, 1, 2] d sorted(c) print(d) # [1, 2, 3] print(c) # [3, 1, 2]同理reverse()是原地逆序返回 Nonereversed(x)返回一个迭代器。切片[::-1]是另一条路它直接生成一个新列表不改变原列表。项目正文里专门提过切片方式因为要复制所有元素所以更占内存但好处是原列表保留。做题时如果题目说“在原列表上逆序”就用list.reverse()如果说“得到逆序后的新列表”用[::-1]或 reversed 更合适。那为什么 sort 不是返回列表因为 Python 想让调用者明确“你是要改这个列表还是要新建一个列表”。如果改变和获取新结果混在一起代码很容易产生歧义。理解了这一点就不会把 None 当成 bug。4.2 key 参数自定义排序才是进阶分水岭默认排序只能排数字大小或字符串字典序但期末常出现“按每个数的数位之和排序”这种题目。此时必须用 key 参数。n int(input()) m int(input()) s list(range(1, n 1)) s.sort(keylambda x: sum(int(i) for i in str(x))) print(s[m - 1])这段代码的意思是把 1 到 n 都放进列表排的时候不直接比 x 本身而是先把 x 转成字符串再逐位转 int 求和用这个“数字和”作为排序键。lambda 是一个没有名字的小函数它接收一个参数 x返回一个“排序时要比较的东西”。由于 Python 的 sort 是稳定排序数字和相同的两个数会保持原来的相对顺序正好符合“数位和相等时按原值从小到大”的常见题意。同样的逻辑还能用来“按第一次出现顺序去重”s1 input().split(,) s2 list(set(s1)) result sorted(s2, keys1.index)s1 是原始顺序s2 是去重后的结果keys1.index让排序参照原始列表的下标等于把“第一次出现的位置”作为顺序依据。项目正文里有个更简洁的总结sort 有两个可选参数key 接收函数reverse 接收布尔值。比如keystr.lower可以让字符串忽略大小写排序这在处理含大小写的姓名列表时很实用。为什么 key 值得单独复习因为默认排序只有一个标准而题目里的排序标准千奇百怪按长度、按末位、按数位和、按出现顺序。学会 key就是学会告诉 Python“别按你默认的排按我指定的规则排。”4.3 桶排序计数器思想是频次统计的核心桶排序是 K12 算法题和期末都喜欢的思路但它的本质不是“高大上”而是“给每个可能的值准备一个桶遍历时往对应的桶里放一个记号”。最经典的场景是统计每个自然数出现次数n int(input()) num_list list(map(int, input().split())) count_dict {} for num in num_list: count_dict[num] count_dict.get(num, 0) 1 sorted_nums sorted(count_dict.keys()) for num in sorted_nums: if count_dict[num] 0: print(num, count_dict[num])这里的 count_dict 就是一组桶以数字为键以次数为值。count_dict.get(num, 0)的意思是如果 num 之前出现过取旧值如果没出现过就当作 0再加 1。这样第一次遇到的数字也能正确入桶。桶排序的好处是一次遍历就能拿到频次信息时间复杂度低。但它有前提数据范围不能太大、太散。如果输入的数字最小 1、最大一亿你不可能开一亿个桶这时更适合用字典按需计数。期末考场上看到“统计出现次数”先不要急着写桶先想想数字范围有多大、有多少个不同的数。桶的思想是对的但“桶”的载体要对。4.4 二分查找有序是它敢“跳着找”的前提二分查找是期末复习点里最有“算法感”的一个。思路用一句话讲在一个已经排好序的列表里每次看中间的数比目标大就到左半边找比目标小就到右半边找不断把范围砍半直到找到或找空。def find(nums, target): left, right 0, len(nums) - 1 while left right: mid (left right) // 2 if nums[mid] target: return mid elif nums[mid] target: left mid 1 else: right mid - 1 return -1注意调用前必须排序。如果列表无序中间值和目标的大小关系不能说明目标在哪一半二分查找就变成了乱猜。很多同学背熟了 while 模板却忘了“先排序”这个前提结果查找失败。复习时要把两件事绑定在一起看到二分查找第一反应不是循环而是“有序”。二分查找的价值在哪里对大规模数据排序一次要 O(n log n)之后每次查找只需 O(log n)。如果有多次查找先排序再二分非常划算。但如果数据量很小排序的损耗可能比直接扫描还大这时候用线性查找就够了。期末不会让你分析复杂度但你至少要知道二分查找不是万能的它的“能”建立在有序之上。5. 常见误区与易混点容易丢分的“想当然”期末复习到最后真正拉开差距的不是大算法而是一堆看起来很小、特别容易想当然的陷阱。下面这五组是最常考、也最常错的。5.1 元组与列表逗号决定命运易混点(3)和(3,)看起来几乎一样但一个是整数一个是元组。为什么混因为很多人以为元组就是“带括号的列表”忽略了元组靠逗号组成而不是靠括号。其实A 1, 2也会得到元组(1, 2)括号更多是为了可读性。怎么区分用type()一看就知道。写元组时单元素必须加逗号(3,)。没有逗号(3)只是普通整数。项目正文里专门强调“元组只有一个元素时需要加逗号”这是期末选择题最直接的考点。另外元组不能原地修改没有 sort、reverse、append 这些方法。想对元组排序只能先转换成列表排完再转回来。很多同学试图用t.sort()立刻报 AttributeError。做题时先问一句我手里的是不是不可变对象是的话所有“原地修改”类操作都别用。5.2 集合与列表去重很方便但别想按下标取易混点集合也能装好多值就误以为能像列表一样用下标访问比如s[0]。为什么混因为打印一个小整数集合时它经常“自己排好序”看起来像有序列表。这种“伪顺序”让人下意识以为它有下标。怎么区分列表是有序的序列用a[0]取第一个集合是无序的容器不支持下标访问也不是所有元素都有位置。整数集合的升序只是它内部存储的副产品不是编程接口。所以del s[0]是错的del s可以删除整个集合但不能删集合里的“第一个”。集合元素还有类型限制可以放元组不能放列表。想验证是不是这样写一句{[1, 2]}就会看到 TypeError。为什么列表不行因为列表可变、可哈希性不稳定集合无法判断“它是不是出现过”。考前记住“元组能进集合列表不能进集合”就够了。5.3 字典的键不可变才是“上岗证”易混点以为字典的键可以像列表下标一样随便换类型甚至拿列表当键。为什么混键从形式上看就是一个值值可以是任何类型于是键也容易被当成“任何类型都行”。怎么区分字典的键必须能被哈希也就是必须不可变。字符串、数字、元组可以当键列表、字典、集合这种可变对象不能当键。因为键相当于字典的“索引标签”如果标签本身会变字典就没法稳定维护对应关系。所以题目问“哪个不能做字典的键”看到带方括号的列表就直接排除。字典的另一个易混点是“双向索引”。你能用键查值但不能用值查键。如果想知道“值等于 x 的键是哪个”必须用 items() 遍历手动比较值。“字典的键不允许重复值允许重复”这两句也要连在一起记。5.4 切片赋值a[:0] 是在开头插入不是取第 0 个元素易混点a[:0]看起来像是在取“第 0 个元素前面的内容”实际上它在等号左边时是“在开头插入”。为什么混因为a[0]是取元素a[:0]多了一个冒号初学者会把它理解成“取一个空范围”不确定空范围能干什么。怎么区分切片返回的是列表的一个区域。a[:0]是“从最开头到下标 0 之前”的空区域等号左边时把右边列表塞进这个空区域结果就是在开头插入x [3, 4] x[:0] [1, 2] print(x) # [1, 2, 3, 4]同理a[0:0]也可以。这个知识点不常让手写但经常出现在选择题里问“执行后列表是什么”。只要记住“冒号出现时右端是切片等号左边时切片的位置用来放新值”就不会慌。5.5 下划线命名_xxx、__xxx、xxx不是一回事易混点看到下划线就以为都是“私有”的意思分不清哪一个才是 Python 真正保护的东西。为什么混三个写法都带下划线教材又喜欢把它们放在同一道题里讲。怎么区分_xxx是约定俗成的“私有”只是一个提醒Python 不拦截__xxx是会被 Python 改名的“私有”解释器会把它变成_类名__xxx外部访问原名会失败__xxx__是 Python 的特殊方法或特殊变量比如__init__是解释器约定好的接口不能随便拿来当私有名。class Student: def __init__(self, name): self._name name self.__score 0 s Student(A同学) print(s._name) # 能访问 print(s._Student__score) # 双下划线被改名期末题常给你一段类代码问“为什么访问 __score 报错”。正确答案不是“它私有”而是“Python 对它做了名称管理真名变成了 _Student__score”。能把这一句说到位判断题基本就拿稳了。提示考试遇到拿不准的结构先用type(x)看类型再用dir(x)看它支持哪些方法。这不是万能药但能挡住八成想当然。6. 期末答题的边界判断什么时候照搬套路什么时候重新想复习资料里的技巧越多越需要判断力。不是每个方法都适用每道题。下面这张表是期末考前最值得过一遍的场景对照需求推荐写法不推荐去重且保留第一次出现顺序sorted(set(原列表), key原列表.index)直接打印set(...)只要去重不管顺序list(set(...))依赖集合顺序做输出原地排序且原列表可以改list.sort()sorted()再去赋值需要一个新排序结果sorted(...)reverse()或原地 sort统计自然数出现次数字典计数再排序键开一个巨大的桶数组多次查找目标值先排序再二分查找不排序直接二分只遍历不修改用元组用列表安全性和速度都不如元组最后一个具体例子。题目说“输入一串逗号分隔的名字去重后按第一次出现的顺序输出”。许多人的第一反应是set(input().split(,))结果输出顺序全乱。正确做法是s1 input().split(,) s2 list(set(s1)) result sorted(s2, keys1.index) print(result)s1 保留输入顺序set 负责去重sorted 用keys1.index把顺序找回。这就是“什么时候用集合去重、什么时候用排序兜底”的典型答案。反过来也有别用的时候。数据量只有两三个数直接比较比任何排序都省事数据范围极大但很稀疏开桶就是浪费原列表后面还要用原顺序就不能原地 sort。期末考的不是“哪种算法最厉害”而是“这道题选哪招不翻车”。我至今记得某次模拟我兴高采烈地把a.sort()的结果直接 print屏幕上明晃晃地输出 None盯了好几分钟才反应过来这个函数改变了列表本身却没有把结果交回来。从那以后我每次复习 Python 都强制自己走一遍三问这个操作改不改原对象返回给我什么会不会破坏后面的数据这份复习资料里的每一条几乎都是类似的“血泪经验”考前过一遍比临时翻课件更能形成自己的判断。希望帮到你。本文还有配套的精品资源点击获取