简介:这份Python期末复习资料面向中小学(K12)阶段学习者,将散落教材中的基础语法与常见考点浓缩成一份可快速翻阅的速查手册,既能用于期末冲刺,也适合日常查漏补缺。资源为单份docx格式,共1个文件,压缩包约865KB,内容按输入输出、字符串处理、列表操作、自定义排序、桶排序、二分查找、函数与模块、异常处理、面向对象等模块有序展开,每个知识点均配有可运行的代码示例,便于边看边练。文档对易混点做了细致区分,如列表去重的两种方式、sort与reverse的差异、深浅拷贝对原列表的影响、整型进制转换示例等,并结合代码片段逐条说明;同时补充了“ifname== 'main'”等实用技巧。目前已有438人学习浏览,尤其适合需要系统梳理Python核心语法与常用算法的K12学生考前集中复习,也可作为平时查阅的随身手册。
1. 这份Python期末复习点:考前最后24小时能做什么
期末复习周,最怕的不是题难,而是笔记又杂又乱。A同学把几十页Python笔记翻过两遍,临考前被问到列表去重为什么要写sorted(set(x), key=x.index),一时答不上来。这份“python期末复习点”就是为这个场景整理的:几十条K12阶段期末考高频考点,从输入输出、字符串、列表、字典、集合,到排序、二分查找、面向对象,全部收进一份清单。
它适合两类人:学完一学期Python的中学生,考前不用从头啃教材,照着清单逐条敲代码验证;带信息技术课的中学老师,拿它当出题范围参考也顺手。它不是教科书,每条考点都短到能直接放进IDLE跑一遍。下面按清单的脉络拆成几个模块,把每条怎么用、考场上容易在哪一步翻车,一次说清楚。
2. 输入输出与字符串操作:三个切分方式和五个print参数
输入输出是每张Python卷子的第一道关卡,看着简单,翻车率却常年排在前三名。问题通常不是不会写,而是对input()返回什么、split()切出什么、print()的几个参数分别控制什么,脑子里没有一张完整的图。这一章先把输入输出和字符串操作里的高频考点过一遍。
2.1 input()、split()与map():多组数据怎么接
先看四种最常见的接收方式,对应四种不同的输入习惯:
# 方式一:把三个数分别转成 int 接收 a, b, c = map(int, input().split()) # 方式二:用单个变量接收,得到字符串列表 data = input().split() # 方式三:用多个变量接收,得到字符串 x, y = input().split() # 方式四:指定逗号作为分隔符 parts = input().split(",")方式一是考试首选。map(int, input().split())把输入字符串按空白切分,再把每个片段转成int,最后通过解包赋值把三个int分别交给a、b、c。注意map返回的不是列表,是一个map对象,这里能解包是因为变量数量和元素数量刚好一致;如果输入是“1 2 3 4”而你只写了三个变量,会直接抛ValueError。
方式二适合不确定输入个数的场景。input().split()返回一个列表,里面每个元素都是字符串。很多同学在这里会犯一个典型错误:不转int就去做加法,结果得到的是字符串拼接,比如“1”+“2”输出“12”而不是3。方式三要求变量个数和切分结果一一对应,多一个少一个都会报错。方式四里split(",")按逗号切分,输入“1,2,3”得到['1','2','3']。
一个容易被忽略的点:split()括号里什么都不写,表示按任意空白字符切分,包括空格、换行、tab;写了逗号,就严格按逗号切。很多题目输入是逗号分隔,直接写成input().split()会得到一整串“1,2,3”,后续处理全乱。拿到题目先看样例输入用什么分隔符,再决定split怎么写。
2.2 print()五个参数:sep、end、file、flush分别控制什么
print()是K12阶段用得最多、理解得最浅的函数。完整形式是print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False),五个参数里objects是打印内容,后面四个才是考点。
# sep:多个对象之间用什么分隔 print("Python", "期末", "复习", sep="-") # 输出:Python-期末-复习 # end:打印结束后追加什么字符,默认是换行 print("第一行", end=";") print("第二行") # 输出:第一行;第二行sep默认是空格,所以print("a", "b")输出“a b”。end默认是\n,所以连续两个print会各占一行;如果想让结果打印在同一行,就把end改成空字符串或分号。考试里常见的是用end=""控制不换行,最后再补一个空print换行。
file和flush考得少,但实用价值很高。file默认是sys.stdout,也就是终端;改成文件对象后,print的内容会直接写进文件。flush默认是False,表示输出先进缓冲区,不急着刷新到终端;调试循环进度时想实时看到输出,可以写成flush=True。
with open("result.txt", "w", encoding="utf-8") as f: print("总分:95", file=f) # 循环里实时查看进度 import time for i in range(5): print("进度", i, end="\r", flush=True) time.sleep(0.5)参数之间的关系用一个表就能看明白:
| 参数 | 默认值 | 作用 | 易错点 |
|---|---|---|---|
| objects | 无 | 要打印的对象,可多个 | 多个对象用逗号分隔,不能用加号拼不同类型 |
| sep | 空格 | 多个对象之间的分隔符 | 想用逗号分隔时必须显式写sep="," |
| end | 换行 | 打印结束追加的字符 | 忘记改end会默认换行 |
| file | sys.stdout | 输出目标 | 传文件对象时必须确保以写模式打开 |
| flush | False | 是否立即刷新缓冲 | 调试实时日志时记得设为True |
2.3 字符串去重、排序、join与strip
字符串处理里,去重、排序、拼接这三件事经常绑在一起考。核心思路是:字符串本身不可变,所以要转成列表操作,完事再拼回字符串。
s = input() # 字符串去重并排序 s1 = list(set(s)) s1.sort() print("".join(s1)) # 如果想去重后保持第一次出现顺序 parts = input().split(",") uniq = sorted(list(set(parts)), key=parts.index) print(uniq) # 去掉字符串两端的空格或指定字符 name = " hello " print(name.strip()) # hello print(name.lstrip()) # hello (右边空格还在) print(name.rstrip()) # hello(左边空格还在)set(s)去重后是无序集合,转成列表再sort,就能得到按字母排序的唯一字符列表。"".join(s1)把列表元素无缝拼回字符串,注意join的用法是分隔符在前:"".join表示元素之间不插入任何字符,",".join表示用逗号连接。
保持顺序那行值得多看一眼。set(parts)去重后顺序是乱的,key=parts.index让sorted按每个元素在原列表里第一次出现的位置排序,输出顺序就和原输入一致。这个写法在列表去重章节还会再出现,是期末卷子上的常客。
strip()系列函数删除字符串两端的字符,不传参数时默认删除空白。partition()是另一个容易被忽略的字符串方法:它按分隔符切成三段,返回一个元组,分别是分隔符前、分隔符本身、分隔符后。
date = "2024-12-31" print(date.partition("-")) # ('2024', '-', '12-31') print("".join(date.split("-"))) # 20241231partition和split的区别在于:split返回列表,把所有切片都切出来;partition只切第一次出现的位置,返回三元组。如果分隔符不存在,partition返回的是原字符串加两个空字符串,这个边界在判断题里出现过不止一次。
3. 列表去重、逆序、自定义排序:三种写法背后的内存差异
列表是K12阶段Python期末考的分值大户。去重、逆序、自定义排序这三类操作,看起来都是两三行代码,实际里头的内存语义和返回值的坑特别多。很多学生代码跑对了,但被问“为什么这样写”就卡住,这一章把每个细节拆开讲。
3.1 列表去重与保序:set、index、dict.fromkeys的区别
列表去重有几种写法,期末题里考的不是“能不能去重”,而是“去重之后顺序还在不在”。
items = ["b", "a", "b", "c"] # 只去重,不管顺序 fast = list(set(items)) # 去重并保留第一次出现顺序 keep = sorted(list(set(items)), key=items.index) # 用 dict.fromkeys 也能保序 keep2 = list(dict.fromkeys(items)) print(fast) # 顺序不稳定,依赖哈希值 print(keep) # ['b', 'a', 'c'] print(keep2) # ['b', 'a', 'c']list(set(items))是最直观的去重写法,但set底层是哈希表,遍历出来的顺序和输入顺序没有任何关系。如果题目要求“按第一次出现的顺序输出”,这种写法就直接翻车。
保序写法有两个思路。第一个是key=items.index,让sorted在比较元素时,用它在原列表里的首次出现位置决定先后;元素本身是什么值,在去重场景里已经不重要,排序键用的是下标。第二个是dict.fromkeys(items),利用字典键不能重复、且Python 3.7以后字典保持插入顺序的特性,先建字典再取键,就得到了保序去重后的列表。
提示:数据量小的时候两种写法都能用。数据量一大,
items.index每次查找都是O(n)扫描,整体效率会明显下降;dict.fromkeys的写法更适合大列表。
3.2 逆序三件套:reverse()、sort(reverse=True)、切片[::-1]
列表逆序有三个常见写法,分别对应三种不同语义。很多同学把它们混成一谈,考试时被问到“哪个会改变原列表”就答错了。
nums = [3, 1, 2] # 写法一:原地反转元素顺序 nums.reverse() print(nums) # [2, 1, 3] # 写法二:按大小降序排序 nums.sort(reverse=True) print(nums) # [3, 2, 1] # 写法三:切片逆序,生成新列表 rev = nums[::-1] print(nums) # [3, 2, 1] print(rev) # [1, 2, 3]reverse()是单纯把列表倒过来:第一个变最后一个,最后一个变第一个,它不关心元素大小。sort(reverse=True)则是先排序再倒序,最后得到的是从大到小的排列。这两个动作完全不同,但结果在某些用例下看起来很像,比如[3, 1, 2]反转是[2, 1, 3],降序排是[3, 2, 1],一眼就能看出来差别。
切片[::-1]最特殊。它不会修改原列表,而是创建一个新列表。nums还是原来的顺序,rev才是逆序后的结果。代价是内存:切片会复制一份完整列表,列表越大,额外占用的内存越多。但反过来,如果题目要求“在不动原列表的前提下输出逆序结果”,切片反而是最省事的。
顺带说一个相关考点:y = x和y = x[:]的区别。前者是让两个变量指向同一个列表,改一个另一个跟着变;后者是浅拷贝生成新列表,两个列表互不影响。但如果列表里还有嵌套列表,切片拷贝的只是外层指针,内层列表对象仍然是同一个,修改内层会互相影响。这是“浅拷贝”三个字的完整含义。
3.3 自定义排序:sort的key参数、lambda与稳定排序
sort()有两个可选参数:key指定排序依据,reverse控制升降序。key参数接收一个函数,列表里每个元素都会先经过这个函数处理,比较的是处理后的返回值,而不是原始元素。
某竞赛真题的数位排序就是经典例子:按数字各位之和排序,而不是按数字本身排序。
n = int(input()) m = int(input()) nums = list(range(1, n + 1)) nums.sort(key=lambda x: sum(int(i) for i in str(x))) print(nums[m - 1])这行lambda看着唬人,拆开就三件事:str(x)把数字转成字符串,for i in str(x)逐位取出字符,int(i)把字符转回数字再求和。最终key返回的是每个数字的数位和。sort按数位和从小到大排;数位和相同时,保持它们在原列表里的相对顺序,这叫稳定排序。题目输出第m个元素,就是按这个规则排完后的第m-1个下标。
另一个常见例子是不区分大小写排序:
words = ["Banana", "apple", "Cherry"] words.sort(key=str.lower) print(words) # ['apple', 'Banana', 'Cherry']key=str.lower让所有字符串先转成小写再比较,这样大写字母开头的Banana不会因为ASCII码靠前而排到最前。回想一下材料里的“字符串排序并去重”那一节,本质也是key参数的应用场景:先用set去重,再用sort排序,最后join拼回。
4. 查找与统计算法:二分边界、桶计数和六个内置函数
K12期末卷子上算法题的比例不高,但一旦出现,基本都是“排序后查找”或者“统计频次”这两个套路。这章把二分查找、桶计数和几个高频内置函数一次讲透,考前直接背模板都比现场推演快。
4.1 二分查找:边界条件与返回值约定
二分查找的前提是列表已排序。它的核心思路是每次取中间位置比较,把搜索区间砍掉一半,复杂度从O(n)降到O(log n)。模板背熟不难,难在边界条件写错。
def find(nums, target): left = 0 right = 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 nums = list(map(int, input().split())) nums.sort() target = int(input()) print(find(nums, target))边界条件的关键是while left <= right。当left和right相等时,mid也等于这个位置,如果target恰好在这里,循环还能继续进去判断;如果写成left < right,只有一个元素时循环根本不进入,直接返回-1,即使这个元素就是要找的目标。很多复习笔记里会用left < right的写法,那是配合循环结束后再补一次nums[left] == target检查的改法。考前建议直接用<=这个标准版本,减少一个容易漏掉的判断。
mid的计算用(left + right) // 2,整数除法取中间下标。nums[mid] < target说明目标在右半区,把left移到mid+1;反之把right移到mid-1。这个+1和-1必须写,否则left和right可能永远收缩不到正确区间,出现死循环。返回值方面,找到返回下标,找不到返回-1,是判题系统最常见的约定。
4.2 桶计数:用字典统计自然数出现次数
统计类题目有个高频需求:给一串自然数,按从小到大的顺序输出每个数和它出现的次数。用字典当“桶”是最舒服的解法。
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 for num in sorted(count_dict.keys()): print(num, count_dict[num])count_dict.get(num, 0)是这套代码的灵魂。当num第一次出现时,字典里没有这个键,get返回默认值0,加1后次数变成1;第二次遇到同一个num,get返回当前次数,再加1。这样就省掉了“先判断键是否存在,存在才加1”的三行if代码。
输出前用sorted(count_dict.keys())对键排序,保证结果是按自然数从小到大输出。如果题目还要求统计哪些自然数没出现在列表里,可以按范围再补一个循环,判断键是否存在。
桶排序思想在这里的体现是:把数字本身当作桶编号,把出现次数当作桶里的值。数字范围小且连续时,也可以用列表当桶:
bucket = [0] * 1000 for num in num_list: bucket[num] += 1列表版的好处是下标天然有序,输出时直接遍历列表下标就行。缺点是数字范围一大,比如从1到10的9次方,开一个这么长的列表就是灾难。K12考试里数据范围通常比较温和,两种写法都能过;实际刷题时建议优先用字典,省内存且不用预先知道数据上限。
4.3 必会内置函数:int进制、divmod、enumerate、isinstance、sample
材料里有一批零散考点,单拎出来每个都不难,但混在一起容易记错。我把最常考的五个集中列一遍。
print(int("123", 16)) # 291,按十六进制解析后转十进制 print(divmod(17, 5)) # (3, 2),商3余2 data = ["a", "b", "c"] for idx, val in enumerate(data): print(idx, val) # 0 a / 1 b / 2 c print(isinstance(3, int)) # True print(isinstance(3.0, int)) # False import random print(random.sample(range(10), 3)) # 从0-9随机取3个不重复的数int("123", 16)的进制参数取值范围是2到36,字符串里每一位数字都不能超过base-1。比如int("12", 2)合法,因为二进制里只有0和1;int("23", 2)会报错,因为2不是二进制数字。这个点在判断题里出镜率很高。
divmod返回的是元组,第一个是整除的商,第二个是余数。K12题目里通常用于“求小时和分钟”“求组数和剩余”这类场景。enumerate默认从0开始计数,如果想从1开始,写成enumerate(data, 1)。isinstance(3.0, int)返回False,因为3.0是float不是int,这也是反直觉考点。random.sample不放回抽样,想允许重复就用random.choices,这两个函数名只差一个字母,考试选择题里专门有人拿这个挖坑。
5. K12期末复习常见问题:五个必踩的语法坑
这一章列五个真实卷面上反复出现的坑。每条按现象、原因、解决三个步骤写,考前过一遍,比做十道新题都管用。
5.1 踩坑一:sort()返回None,赋值之后一片空白
nums = [3, 1, 2] result = nums.sort() print(result) # None现象:写完result = nums.sort(),打印result输出None,以为排序失败了。
原因:list.sort()是原地排序方法,它直接修改nums,不返回新列表。Python里这类原地方法约定返回None,reverse()也一样。很多初学者在这里惯性思维,以为所有函数都有返回值。
解决:不需要接收返回值,先调用sort,再用原列表变量:
nums = [3, 1, 2] nums.sort() print(nums) # [1, 2, 3] result = sorted(nums) # sorted才有返回值 print(result) # [1, 2, 3] print(nums) # [1, 2, 3]x.sort()改的是x本身,返回值是None;sorted(x)不改变x,返回一个排好序的新列表。这两者方向相反,优先级最高,先背下来再刷题。
5.2 踩坑二:set去重把顺序搞乱了
items = ["b", "a", "b", "c"] print(list(set(items))) # 输出顺序不稳定,可能是 ['a', 'b', 'c'],也可能是别的顺序现象:用set去重,结果出来顺序和原列表不一样,有时候同一段代码跑两次结果还不一样。
原因:set是哈希表结构,元素存储位置由哈希值决定,天然没有顺序概念。把列表转成set再转回列表,顺序就不可控了。K12考卷里如果题目明确要求“按原顺序去重”,直接list(set(...))拿不到分。
解决:去重加保序,用sorted配合原列表下标:
items = ["b", "a", "b", "c"] result = sorted(list(set(items)), key=items.index) print(result) # ['b', 'a', 'c']items.index返回每个元素在原始列表里第一次出现的位置,sorted按这个下标排,去重后的顺序就和原列表一致了。数据量大时可以用dict.fromkeys(items)代替,效果一样,速度更快。
5.3 踩坑三:浮点数比较“不等于”
print(0.4 - 0.1 == 0.3) # False现象:0.4减0.1数学上等于0.3,Python却输出False,看起来像灵异事件。
原因:浮点数在计算机里是二进制存储的,0.4和0.1都无法精确表示,0.4 - 0.1算出来的结果其实是一个很接近0.3但不等同于0.3的值。这不是Python的bug,是所有编程语言共有的浮点数精度问题。
解决:判断浮点数接近时,用math.isclose():
import math print(math.isclose(0.4 - 0.1, 0.3)) # Trueisclose接受两个参数,比较时允许存在一个很小的误差范围。期中卷还有种考法是把两边都转成round后的定点小数再比较,也可以,但isclose语义更清晰。顺带记住:题目里如果出现sqrt(4),结果也是浮点数2.0,不是整数2,这是同一类考点。
5.4 踩坑四:列表当字典键报TypeError
d = {[1, 2]: "x"} # TypeError: unhashable type: 'list'现象:用列表当字典的键,程序直接报错,看不懂报错信息里的unhashable是什么意思。
原因:字典键必须是不可变类型,因为键需要计算哈希值来定位存储位置;列表可变,哈希值无法稳定,Python拒绝把它当作键。不可变类型包括数值、字符串、元组;可变类型包括列表、字典、集合。这个分类也是期末选择题的热门选项。
解决:把列表换成元组当键:
d = {(1, 2): "x"} print(d[(1, 2)]) # x注意元组里也不能塞列表,否则元组变相可变,照样unhashable。类似规则还有:集合的元素可以是元组,但不能是列表;元组只有一个元素时必须写逗号,(3)是整数,(3,)才是元组。
5.5 踩坑五:没写入口保护,模块一导入就执行测试代码
# 文件名 test_helper.py def add(a, b): return a + b print(add(1, 2)) # 一导入就输出3现象:在另一个文件里import test_helper,控制台莫名其妙输出3,明明没有调用任何函数。
原因:模块导入时,顶层代码会从上到下全部执行一遍。写在函数外的print是顶层代码,不是函数体,所以import的瞬间就被执行了。本意是测试add函数,结果污染了导入方的输出。
解决:把测试代码放进入口保护,这是材料里“保证代码可重用性”那句的完整含义:
def add(a, b): return a + b if __name__ == "__main__": print(add(1, 2))直接运行test_helper.py时,__name__的值是"__main__",测试代码会执行;作为模块被import时,__name__是模块名test_helper,测试代码跳过。这样写既保留了测试功能,又不影响被引用时的行为。期末卷子常以判断题形式考这个点,问“被import时if分支会不会执行”,答案是会,只是条件不满足。
6. 考前自测清单:十五分钟把高频考点过一遍
复习到最后,比做题更有效的动作是自测。把知识清单盖住,只看考点名字,现场默写代码,能写出来才算真正掌握。我一般让A同学考前十五分钟做这件事,只过代码不过理论,效率远高于再刷一套新题。
6.1 高频考点自测表
| 考点 | 自测写法 | 自查提示 |
|---|---|---|
| 多int输入 | a,b,c = map(int, input().split()) | input()后面有没有括号 |
| 字符串去重排序 | "".join(sorted(set(s))) | 结果别忘了拼回字符串 |
| 列表保序去重 | list(dict.fromkeys(x)) | key=x.index只适合小列表 |
| 原地排序 | x.sort()后直接使用x | 不要接收返回值 |
| 逆序新列表 | y = x[::-1] | 这是浅拷贝,新对象 |
| 二分查找 | while left <= right | 单元素列表也要能查 |
| 频次统计 | d[k] = d.get(k, 0) + 1 | 首个元素不再KeyError |
| 单元素元组 | t = (3,) | 没有逗号就是int不是元组 |
6.2 考前最后十分钟的固定动作
自测时不要只盯着能写出来的部分,重点看写错的那些。比如sort()返不返回None、切片逆序要不要额外内存、set去重丢不丢顺序,这些点单独背都能背住,一旦和真实代码结合起来就出错,本质是缺少运行验证。把每次写错的代码存成一个错题文件,考前只看错题文件,比把笔记从头翻到底管用得多。
从那以后我每次组织考前复习,都强制要求先把这张自测表跑一遍,十五分钟扫完高频错点再进考场。A同学以前是“一看就会、一写就错”的状态,靠这个动作把丢分率压下去了大半。希望帮到你。
本文还有配套的精品资源,点击获取