简介:面向 K12 阶段 Python 初学者的期末复习要点文档,围绕输入输出、字符串、列表、排序算法、二分查找、函数与模块、异常处理和面向对象编程等高频考点,整理成便于考前快速浏览的复习提纲。资源包共 1 个 docx 文件,约 865KB,内容按知识点分块呈现,并配有可直接运行的代码示例;已有 439 人学习下载。文档特别强调常见易错点,例如 input().split() 与 map 的多数据输入写法、print 的 sep/end 控制、字符串排序去重与保序去重、sort 的 key/reverse 参数、列表 reverse 与切片逆序的内存区别,以及 ifname== 'main' 的模块化用法;同时给出桶排序统计频次、二分查找模板、lambda 自定义排序等可套用写法。末尾还整理了 Python 复习判断题式要点,覆盖可变与不可变数据类型、深浅拷贝、列表 pop/del 等细节,方便学生自测薄弱点,也适合教师作为考前梳理参考。
1. Python期末考点分布:先弄清这门课到底考什么
很多人复习 Python 期末,习惯把课本从头翻到尾。结果一上考场,看到0.4 - 0.1 == 0.3这道题,第一反应填 True,直接丢分。这不是基础差,是没摸清这门考试的出题脾气。Python 期末的高频考点其实很集中:输入输出、字符串处理、列表排序去重、桶排序和二分查找几个算法模板,再加上一组专门挖坑的概念题——比如x.sort()返回 None、sqrt(4)的结果是 2.0、A=(3)不是元组。把这些点逐个击破,比盲目刷题高效得多。这篇备考笔记面向正在复习 python 期末的 K12 学习者,按考点分布、高频题型、易错陷阱、答题策略四层拆开,让你在期末考场上少丢不该丢的分。
2. 输入输出与字符串:必考模板与print参数拆解
输入输出几乎是所有 Python 期末试卷的第一道大题。这部分的考察不是背语法,而是给定输入格式,让你写读入和输出的代码。很多翻车现场都出在split()和map()的组合使用上。只要把下面三种连续输入的模式吃透,这类题基本就是送分。
2.1 input().split() 与 map():连续输入的套路
先看最常见的读入模式:
a, b, c = map(int, input().split())这行代码干了三件事:input()读入一整行字符串;.split()按默认空白(空格、制表符、换行)把字符串切成若干段;map(int, ...)把每一段转换成整数,然后分别赋给 a、b、c。注意这里必须写成input().split(),括号不能省,不少考生抄笔记时写成input.split(),运行时直接报错。
A = input().split() # 返回字符串列表,如 ['12', '34', '56'] a, b = input().split() # 两个变量各接收一个字符串当一个变量接收时,得到的是一个字符串列表;当多个变量接收时,每个变量拿到一个字符串。这个区别经常考察"执行后变量类型是什么"。如果题目要求接收的是整数,就必须套map(int, ...)或逐个int()转换,否则后面做加法会拼成字符串而不是数值相加。
提示:
split()括号里可以指定分隔符,比如input().split(',')表示按逗号分割。默认分隔符是任意空白字符,这是大多数题目默认的输入形式。
2.2 print() 参数拆解:sep、end、file、flush
print()的完整签名在期末中高频出现,尤其是判断输出结果类的题目:
print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)objects:一次可以输出多个值,逗号隔开sep:多个值之间的分隔符,默认一个空格end:输出结尾字符,默认换行file:输出流向,默认标准输出 sys.stdoutflush:是否立即刷新缓冲区,默认 False
print(1, 2, 3, sep=',', end='!')输出的是1,2,3!。期末题常让你判断输出结果,或者让你用sep=''去掉空格、用end=''不换行。这个表格建议考前背一遍:
| 参数 | 默认值 | 作用 | 常考场景 |
|---|---|---|---|
| sep | 空格 | 多个输出对象之间的分隔符 | sep=',' 拼接输出 |
| end | 换行 | 输出末尾追加的字符 | end='' 实现不换行 |
| file | sys.stdout | 输出目标 | 概念判断题 |
| flush | False | 是否清空缓冲区 | 概念判断题 |
最容易被绕进去的是sep和end的分工:sep管的是"两个输出值之间",end管的是"整条输出结束时"。题目里如果把sep=','和end='!'混着出,先写清楚数据再套参数,基本不会错。
2.3 字符串排序去重与 join() 拼回
字符串去重排序是期末的经典输出题,模板如下:
s = input() # 读取字符串 s1 = list(set(s)) # set 去重,list 转成列表 s1.sort() # 按 ASCII 码排序 print(''.join(s1)) # 用空字符串拼接还原成字符串输出set(s)会去掉重复字符,但集合本身无序,所以必须紧接着sort()按字符编码排序,最后再用''.join(s1)把列表拼回字符串。很多人直接输出set转出来的列表,结果带引号和逗号,格式分白丢。注意''.join()括号里只能放"由字符串组成的列表",如果列表里有数字,需要先str()转换。
真题练习:输入一行小写字母,去掉重复字符后按字典序输出。输入bdacdab,输出abcd。
答题思路:第一步确定数据流——读入字符串 s,list(set(s))得到去重后的字符列表,排序后用''.join输出。模板默写出来,不要现场想。如果需要保持原字符串中首次出现的顺序,set就不适用,要改成sorted(set(s), key=s.index),这时key会按每个字符第一次出现的位置编号排序。
字符串本身是不可变类型,所有对字符串的"修改"都会产生新对象。如果题目要求从字符串中删除某些字符,''.join(x.split())是常见技巧——先用split('a')按指定分隔符切开,再用空串拼回去,就相当于删除了这些分隔符。类似地,strip()删除字符串左右两端的指定字符,lstrip()、rstrip()分别删除左端、右端,默认都处理空白字符。
3. 列表排序与去重:三条主线和三种逆序写法
列表在期末试卷里的出镜率最高,而且通常是组合题:读入列表、去重、排序、输出,一步接一步。这章把三条主线串起来:去重保序、原地排序与返回新列表的区分、以及自定义 key 排序。最后再单独对比逆序的三种写法。
3.1 列表去重保序:set 配合 index 的经典写法
s1 = input().split(',') # 按逗号分割读入,得到字符串列表 s2 = list(set(s1)) # set 去重,但顺序会被打乱 print(sorted(s2, key=s1.index)) # 按原列表首次出现顺序排序后输出list(set(s1))只负责去重,不保证顺序。要让去重后的元素按它们第一次出现的位置排序,就让key=s1.index。s1.index(x)返回 x 在原始列表中的下标,sorted会把它当作排序依据,顺序就恢复了。数据量小时这个写法简单够用;如果数据量大,index是 O(n) 查找,整体偏慢,更稳的做法循环遍历手动去重。
摘要里提到的list(dict.fromkeys(s1))是另一个保序去重方案。dict.fromkeys用列表元素作键创建字典,后续重复的键会被保留第一次的位置,再转回列表就是保序去重,需要在一行内解决时非常好用。它依赖字典的插入顺序特性,期末选择题如果考"哪个写法能保序去重",选这个通常没错。
3.2 sort() 与 sorted():谁改谁不改
这是期末最高频的考点之一,而且必带一个坑。看代码:
x = [5, 1, 3] print(x.sort()) # None,sort 是原地排序,没有返回值 print(x) # [1, 3, 5],x 已经被修改 y = [5, 1, 3] print(sorted(y)) # [1, 3, 5],返回新列表 print(y) # [5, 1, 3],原列表没变sort()是列表的原地方法,直接修改原列表,返回值是 None;sorted()是内置函数,返回一个排好序的新列表,原列表不动。考试里最容易手滑写成x = x.sort(),这一写 x 就变成 None 了,后续所有操作全崩。正确做法是单独一行x.sort(),之后再使用 x。
另一个注意点是x.reverse()同样是原地操作,返回值也是 None。真题里出现过"以下代码输出什么"的题型:先x.sort()再print(x)输出排序后的列表;但如果直接print(x.sort()),输出的就是 None。做题时先想清"这个操作改不改原列表、返回什么值",再决定怎么写。
3.3 自定义 key 排序:数位排序的实战拆解
自定义排序是期末的压轴题风格之一,最典型的例子是按各位数字之和排序。题目通常给出 n 和 m,要求把 1 到 n 的数字按"各位数字之和"从小到大排,再输出第 m 个数。
n = int(input()) m = int(input()) s = list(range(1, n + 1)) # 生成 1 到 n 的列表 s.sort(key=lambda x: sum(int(i) for i in str(x))) # 按各位数字之和排序 print(s[m - 1]) # 输出第 m 个,下标记得减 1key参数接收一个函数,这个函数对列表里每个元素算出一个"排序键"。lambda x: sum(int(i) for i in str(x))先把数字 x 转成字符串,逐位取字符再转回整数求和,得到各位数字之和。sort会按照这个键从小到大排列,而每个元素本身仍然保留原值。整个过程没有显式交换任何元素,这就是 key 定制排序的意义。
这种题的答题思路是三步:构造列表、写 key 函数、索引输出。考试时如果记不住 lambda 怎么写,可以先写一个普通函数,再传给 key,效果一样。容易漏掉的是s[m - 1]的下标偏移——题目说第 m 个,索引要从 0 开始,所以必须减 1。
3.4 逆序输出的三种写法与内存视角
逆序输出是送分题,但送分也分三档。先看代码:
a = [3, 1, 2] a.sort(reverse=True) # 降序原地排序,原列表被改 print(a) # [3, 2, 1] b = [3, 1, 2] b.reverse() # 反转位置,原地操作,原列表被改 print(b) # [2, 1, 3] c = [3, 1, 2] print(c[::-1]) # 切片反转,返回新列表,原列表不变 print(c) # [3, 1, 2]三种写法的差异集中在"是否改原列表"和"是否复制内存":
| 写法 | 是否改原列表 | 返回值 | 内存说明 |
|---|---|---|---|
| list.sort(reverse=True) | 改 | None | 不额外复制列表 |
| list.reverse() | 改 | None | 不额外复制列表 |
| list[::-1] | 不改 | 新列表 | 复制一份全部元素 |
考试题如果要求"不改变原列表输出逆序",用print(c[::-1]);如果要求"原地逆序",用c.reverse();如果题目给了排序和逆序两个要求,就在sort(reverse=True)上做文章。切片反转虽然直观,但它是新建副本,列表大时内存翻倍,这也是一个潜在的扣分理由。
4. 算法专题:桶排序与二分查找的考场写法
期末程序题里出现频率最高的两个算法模板,一个是桶排序(统计频次),一个是二分查找。它们不算难,但细节决定能否满分,尤其是二分查找的边界条件。这章把两个模板拆成可以直接默写的代码块,再补上输出格式的踩点。
4.1 桶排序的字典计数模板
题目通常这样出:读入一个整数 n 和 n 个自然数,统计每个自然数出现多少次,按自然数从小到大输出,每行一个"数 次数"。
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.get(num, 0) + 1。get在键不存在时返回默认值 0,所以第一次遇到某个数时计数从 1 开始,之后每遇到一次加 1。最后sorted(count_dict.keys())按自然数从小到大遍历,把每个数和出现次数以"数 次数"格式输出。这里字典的键就是桶,键是自然数,值是出现次数,构成了桶排序的基本形态。
实际写题时需要注意:题目如果没有要求按顺序输出,有些人会直接遍历count_dict,但字典的遍历顺序不一定等差有序。记住一个原则——输出前先想清楚"输出顺序由谁决定",需要有序就sorted,省得白丢格式分。另外n这个变量虽然在示例里读入了,但后续统计靠的是num_list,不要被输入格式干扰。
4.2 二分查找的边界与返回值
典型的期末程序题:读入一串数,排序后查找目标值的下标,查到返回下标,查不到返回 -1。输入第一行是列表长度,第二行是列表元素,第三行是要找的目标值。
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 a = list(map(int, input().split())) a.sort() # 二分前提:必须先排序 target = int(input()) print(find(a, target))二分查找有两个必须讲清的细节。第一,条件是left <= right还是left < right?如果写成left < right,当区间里只剩一个元素时循环就停了,此刻这个元素还没被检查,极容易漏判,比如列表只有一个数且就是要找的目标,返回的却是 -1。所以期末想稳,就统一用left <= right。第二,mid = (left + right) // 2用整除取中间下标;当nums[mid] < target时,说明目标在右半边,left = mid + 1,反之right = mid - 1,这一步的目的是排除已经检查过的 mid。最后循环还没找到就返回 -1。
提示:先排序再二分。
find内部假设nums是非降序的。如果题目输入自带顺序但不能保证,先nums.sort()再做二分,这一行往往就是满分和零分的差距。
4.3 两个题型的输出格式踩点
桶排序的输出样例通常是:
2 1 3 2 5 1每行一个数加一个空格加出现次数,正好对应print(num, count_dict[num])默认用空格分隔、换行结尾。二分查找的输出则只有一个数,下标或 -1。这两类输出都不要再额外拼空格或换行,print的参数格式本身就是最稳的——多加了空格反而会判输出错误。
程序题的最后检查建议按顺序看三处:输入格式和split()的分隔符是否一致;原列表有没有排序(二分)或输出前有没有排序(桶排序);输出格式和样例是否逐字符一致。这三处检查完,算法题基本不会失分。
5. 易错点:期末高频失分陷阱清单
这一章把所有期末试卷里反复出现的坑集中列出来。每一条都按"错在哪 → 为什么错 → 怎么答对"来讲,考前最后一天就看这份清单。概念题的失分往往不是不会,而是踩了这些预设的陷阱。
5.1 类型与比较的陷阱
第一坑:A = (3)被当成元组。错在以为加圆括号就是元组。(3)里的圆括号只是数学运算的优先级符号,所以type(A)是整数;要定义单元素元组必须加逗号:A = (3,)。判断方式很简单,看逗号,不看括号。
第二坑:0.4 - 0.1 == 0.3填 True。错在对浮点数精度没有概念。0.4、0.1 在二进制里都是无限循环小数,存储时被截断,算出来的结果只能接近 0.3,不能完全相等。正确的接近判断用math.isclose(0.4 - 0.1, 0.3)。
第三坑:拿复数比大小。复数只有相等和不等两个判断,没有大于小于。概念题里出现过"复数之间可以比较大小"的选项,直接判错。同理,元组之间的比较是从左到右逐个元素比较,元素类型不同就无法比较。
A = (3) print(type(A)) # <class 'int'>,不是元组 A = (3,) print(type(A)) # <class 'tuple'> import math print(0.4 - 0.1 == 0.3) # False,浮点数精度问题 print(math.isclose(0.4 - 0.1, 0.3)) # True还有一个高频概念:可变与不可变类型。可变数据类型是列表、字典、集合;不可变数据类型是数值、字符串、元组。期末判断"元组是否可变"这类题,答案一定是"元组不可变"。又因为字典的键必须不可变,列表不能作为键,字符串和元组可以——这个点常借"哈希"的名义一起考。
5.2 拷贝与原地操作的陷阱
第一坑:x = x.sort()直接把数据弄丢。错在不知道sort()是原地操作、返回值是 None。赋值之后,x 的实际值变成 None,后面不管怎么用都是错的。正确写法是x.sort()之后再用 x。同理还有x.reverse()。
第二坑:y = x之后改 y,x 也变了。错在把赋值当成复制。y = x只是让 y 和 x 指向同一个列表对象,id 相同,任意一边修改都会互相影响。要复制内容用y = x[:]或y = x.copy(),这时得到浅拷贝,新列表独立存在。注意切片拷贝只拷贝最外层,嵌套列表里的子列表仍然是共享的,这个可以当额外考点记。
第三坑:想用del删除集合中的部分元素。集合不支持下标访问,也就不能像列表那样按位置删除。del可以删除整个集合,或者用remove(x)删除指定元素。判断题如果出"del 可以删除集合中任意一个元素",答案是错的。
x = [3, 1, 2] print(x.sort()) # None,sort 返回值是 None x = [3, 1, 2] y = x # 赋值,y 和 x 指向同一个列表 y.append(4) print(x) # [3, 1, 2, 4],x 也被改了 s = {1, 2, 3} # del s[0] # 报错,集合不支持下标删除 s.remove(2) print(s) # {1, 3}5.3 字符串、进制与内置函数的陷阱
第一坑:int('123', 16)到底等于多少。这个函数是把"十六进制表示下的字符串 123"转换成十进制数值。按位权展开:1*16^2 + 2*16 + 3*16^0 = 256 + 32 + 3 = 291。很多人算成 123 或 1+2+3,都是没搞懂"进制转换是位权求和"。进制参数必须在 2 到 36 之间,且每位数字必须小于进制数,否则会报错。
第二坑:strip()以为只去空格。实际上strip()默认删除字符串左右两端的空白字符,包括空格、制表符、换行。想删指定字符可以传参数,比如s.strip('a')只删首尾的字母 a。如果不了解默认行为,容易在判断空白字符串时翻车。
第三坑:split()和join()的方向搞反。字符串以某字符分割后返回的是列表,列表以某字符拼接返回的是字符串,方向恰好相反。期末的格式判断题最爱考这一对,答案总是"分割出列表、拼接收回字符串"。
print(int('123', 16)) # 291,十六进制转十进制 s = ' python ' print(s.strip()) # 'python',去掉首尾空白 print(s.lstrip()) # 'python ',只去左边 print(s.rstrip()) # ' python',只去右边 print('a,b,c'.split(',')) # ['a', 'b', 'c'] print('-'.join(['a', 'b'])) # 'a-b'第四坑:忘记if __name__ == '__main__':的作用。这一行是为了保证代码的可重用性:被当作模块导入时,模块内的这段代码不会执行;只有直接运行当前脚本时才执行。判断题选项里出现"防止循环导入""保证代码不被执行"之类的描述,都是错的,正确说法是"保证代码可重用"。
6. 应试策略:答题顺序与一套自检清单
期末程序题的丢分,往往不是不会,而是顺序乱了。拿到卷子先做两件事:快速扫一遍题目,把"概念判断题"和"写代码题"分开;写代码题又按"先背模板再改参数"的顺序推进。比如读到输入输出格式,直接先默写input().split()或map(int, input().split()),别在草稿纸上推演语法。
代码写完不要立刻看下一题,先过一遍必查清单。第一,输入部分有没有写成input.split(),少了括号的调用会导致运行直接报错。第二,split()的分隔符跟题目给的输入格式是否是同一个,一个逗号和空格的区别,会让后半段全部白写。第三,有没有该排序没排序。二分查找的前提是有序序列,桶排序输出要按自然数顺序,这两处是最容易被判零的原因。第四,输出格式跟样例对照一遍,多了空格或者少了换行,在小分题上很吃亏。第五,凡是涉及原地操作的sort()、reverse(),绝不能用它的返回值继续参与计算。
我自己备考的时候养成了一个很笨但有效的习惯:每写完一段代码,强制自己在脑子里跑一个最小输入样例,三四个数就够。比如二分查找就单独测一个长度为 1 的列表,去重排序就测一个全是重复字符的字符串,这个概念题就测A=(3)的type输出。这个习惯救过我太多次,从那以后,我每次交卷前都强制自己走一遍这个流程。期末不像竞赛,它考的就是稳,少丢一个格式分都是赚到的。希望帮到你。
本文还有配套的精品资源,点击获取