news 2026/10/8 11:52:06

董付国Python小屋61-70题复盘:核心考点与高频坑位解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
董付国Python小屋61-70题复盘:核心考点与高频坑位解析

刷完董付国老师的Python小屋编程题61-70,我最大的感受是:这些题表面上看是在考语法,实际上是在逼你建立“用代码解决问题的思维框架”。作为国内Python教学圈里流传很广的一套练习,Python小屋的题目一直以“知识点覆盖扎实、难度梯度合理”著称,尤其是61到70这十道题,恰好卡在基础语法刚讲完、面向对象还没正式深入的阶段,非常适合用来检验自己对字符串处理、类型转换、列表操作、函数封装这些核心基本功的真实掌握程度。

先说结论:如果你现在正处于“能看懂参考答案,但合上书自己写就卡壳”的阶段,这组题是很好的试金石。我当年刷题时犯过不少蠢错误,后来带学生做练习时又看着他们踩进同一个坑,所以这篇博文不打算搬运题目和答案,而是把这十道题背后的出题逻辑、必考知识点、常见错误和排查方法整理出来,希望能给正在刷题的人一些真正有用的参考。

1. 这十道题到底在考什么:知识点分布与难度编排逻辑

董老师的题目从来不是随手出的。我刷完61-70这组题后,特意把所有涉及的知识点列了一张表,发现出题思路非常清晰——这个阶段集中火力在四个方面:字符串处理、数字与类型转换、列表/字典操作、函数封装。这四块恰好是Python基础语法学完之后、进入更复杂项目之前必须打牢的地基。

1.1 为什么中间段位偏偏卡在这几个知识点上

先看一张我整理的知识点分布表,对照自己刷题时的直观感受:

核心考点常见出题形式容易栽跟头的地方
字符串切片与格式化截取子串、反转、拼接、格式化输出切片边界写错、格式化符号用混
类型转换字符串转数字、数字转字符串int()与float()的适用场景混淆
列表增删改查与排序去重、排序、筛选、逆序排序时原列表被误改
字典的键值操作统计频次、按值排序、键值互换访问不存在的键直接报错
循环与条件组合多条件筛选、嵌套遍历循环内修改正在遍历的列表
函数封装抽公共逻辑、返回多个值默认参数使用不当

注意看,这六类考点里没有一项是“偏难怪”的知识点。换言之,这组题不是考你会不会某个冷门函数,而是考你在写普通业务代码时最常用到的那些操作是否熟练。我自己的体会是:刷到中间段位的练习题时,题目本身的难度已经不体现在“懂不懂语法”上,而是体现在“能不能在头脑中快速把需求翻译成代码结构”上。

1.2 题目编排的隐性递进关系

大多数人在刷题时只关注单道题的解法,很少有人会去琢磨题与题之间的前后关系。我复盘时发现,61-70这十道题的编排是有明显的递进意图的:

刚开始的题目往往只涉及一个知识点,比如纯粹的字符串处理、单个列表排序,目的是让你把单项操作练熟。中间的题目开始出现两个知识点的组合,典型的是“字符串处理+类型转换”或者“列表筛选+排序”。到后面几道题,则会要求你封装函数、返回多个结果,这是从“会写一段代码”到“会设计一段代码”的过渡。

理解这个递进逻辑很关键。你刷到后面不会做了,不应该急着去翻答案,而是应该倒回去想:前面那些基础操作我是否真的完全掌握了?以我的经验,八成以上做不出来的情况,根因都在前面的单项技能有漏洞,而不是综合应用能力差。

2. 字符串与数字处理:几乎所有题目都绕不开的基本功

不论61-70在你这套题里具体出现了什么排序、去重、还是统计类的题,字符串处理都是绕不开的底层能力。而且这一块有个特点:语法简单,但细节极多,每一个小坑都足以让你的程序直接报错或者输出错误结果。

2.1 类型转换的边界:int()、str()、float()真没那么随便用

很多初学者觉得类型转换不就是int(“123”)或者str(456)嘛,有什么好讲的。但实际做题时,转换失败的场景才最考验人。

先说最常见的坑:int()只能处理“看起来像整数”的字符串。你写int("12.5"),Python会直接抛ValueError,因为“12.5”在int的眼里不是合法整数文本。同样,float("abc")也会报错。所以凡是涉及“从用户输入或文件读取的数据”转成数字的题目,第一件事永远是确认数据长什么样。

还有一个容易被忽略的点:布尔值其实是整数的一个子类。True == 1、False == 0在Python里是成立的。这就意味着,如果题目里要求你统计某个字符串里满足条件的字符个数,你随手写total += (ch >= 'a')是能跑的——因为True会被当成1来累加。这种写法虽然能过,但可读性极差,我自己带练习时碰到学生写出这种代码,都会建议改回显式的if判断。

# 常见类型转换的正确姿势 s = "123" num = int(s) # 正常,num = 123 t = "12.5" f = float(t) # 正常,f = 12.5 # num2 = int(t) # 报错:ValueError,int不能直接处理带小数点的字符串 # 安全转换的通用写法 def safe_int(value, default=0): try: return int(value) except (ValueError, TypeError): return default

2.2 切片操作:步长和方向是最容易被忽略的细节

字符串切片的格式是s[start:end:step],这个语法看着简单,但一到具体题目里就洋相百出。最常见的错误有两个。

第一个是边界混淆。Python切片是左闭右开区间,也就是[start, end),end位置的字符是不包含的。很多人在切"abcdefg"想取前三个字符时写成s[1:3],取到的却是"bc"。第二个是步长为负时容易绕晕。s[::-1]是反转字符串,这个技巧几乎每套练习题都会出现,但很少有人去深究为什么它能反转——实际上是从末尾往开头逐个取。

以我刷题的经验,切片题做错之后最好的调节方式,是把字符串写在一张草稿纸上,标好每个字符的下标,然后从左到右走一遍切片过程。一旦你真刀真枪地手动模拟过几次,边界错误基本就能杜绝。

s = "0123456789" print(s[2:5]) # 输出 "234",注意不包含下标5 print(s[:5]) # 输出 "01234",start缺省从0开始 print(s[5:]) # 输出 "56789",end缺省到最后 print(s[::2]) # 输出 "02468",隔一个取一个 print(s[::-1]) # 输出 "9876543210",整个反转 print(s[7:2:-1]) # 输出 "76543",从下标7倒着取到下标3(左开右闭,反向时end不含)

2.3 格式化输出的三种方式,实战中到底选哪种

字符串格式化在练习题里出现频率极高,考试题目经常要求输出特定格式的结果,比如保留几位小数、对齐、补零。现在Python里主流有三种方式:%格式化、str.format()、f-string。

我个人的建议很直接:新写的代码一律用f-string。原因很简单,可读性最好,变量直接写在字符串里,不会出现格式串里变量顺序写错的低级问题。%格式化现在只在维护老代码时才会碰到,str.format()虽然功能最全,但绝大多数场景下都显得啰嗦。

name = "董老师" score = 87.5 # 不推荐:%格式化 print("姓名:%s,分数:%.1f" % (name, score)) # 一般般:str.format print("姓名:{},分数:{:.1f}".format(name, score)) # 推荐:f-string print(f"姓名:{name},分数:{score:.1f}")

说一个实际刷题时的细节:f-string里的大括号是特殊符号,如果你需要输出一个大括号本身,得写成{{}}。当初刷题时就见过一道让输出JSON样例的题,好几个人卡在这里想不通为什么输出总缺大括号。

2.4 字符串类题目的通用解题模板

刷完这十道题,我把字符串类题目的解题套路归纳成三步:先想清楚输入是什么、需要切出什么、最终要拼成什么样。以常见的“统计字符串中各字符出现次数”为例,标准思路是遍历字符串,用字典做累计:

text = "python programming" counter = {} for ch in text: # 用get方法避免健不存在的报错 # 这里其实也用到了一点文件读取的思路 counter[ch] = counter.get(ch, 0) + 1 print(counter)

这里有一个非常容易踩的坑:Map和字典的键访问顺序问题。你直接写counter[ch] += 1如果ch是第一次出现,程序就会抛出KeyError,因为字典里还没有这个键。正确的做法是先用get方法给定默认值,或者用defaultdict。这类细节就是练习题想考察的——语法书里都写了,但没写过代码的人到了真实场景就是想不起来。

3. 列表操作与筛选:从“会写循环”到“会选工具”

刷到61-70这个阶段,列表相关的题目难度通常不再停留在“增删改查”基础操作,而是开始要求你做筛选、去重、排序、变换这类数据处理工作。可笑的是,越是这样基础的操作,越容易写出冗长且容易出错的代码。

3.1 列表推导式:一个式子代替三行循环

很多初学者习惯用传统的for循环加append来构建新列表,比如:

# 传统写法 result = [] for x in numbers: if x % 2 == 0: result.append(x)

上面的代码没问题,但如果你刷题时发现自己每个列表操作都要写三到五行,效率就明显低了。列表推导式可以把整段逻辑压缩成一行,而且性能通常更好:

numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] result = [x for x in numbers if x % 2 == 0]

列表推导式的核心语法就三个部分:输出表达式、遍历来源、过滤条件。初次接触的人可以把它们当成“for循环的一行版”来理解,但刷题时必须刻意练习用它,因为后面的题可能会在一个表达式里嵌套两个循环,不熟练的话读都读不懂。

3.2 排序与去重:sorted的key参数是真正的分水岭

先说排序。list.sort()是就地排序,直接改原列表,返回值是None;而sorted()是排序并返回新列表,原列表不变。这两者的区别几乎每套练习题都会考一次。在需要保留原数据的题目里用错sort,结果就是原列表被悄无声息地改了,后续代码全乱套。

再说key参数。这是排序题里边最重要的内容。比如你想按字符串长度排序,或者按字典的value排序,都要靠key来指定:

words = ["python", "java", "c", "javascript"] # 按长度从短到长排序 words_sorted = sorted(words, key=len) scores = {"张三": 88, "李四": 92, "王五": 78} # 按分数从高到低排序 ranked = sorted(scores.items(), key=lambda item: item[1], reverse=True)

对字典按值排序,这个操作在练习题里出现的频率非常高。很多人第一次看到sorted(scores.items(), key=lambda item: item[1])会有点懵,其实拆开看很简单:scores.items()返回的是(键, 值)元组的列表,lambda item: item[1]就是告诉排序函数“拿每个元组的第二个元素当排序依据”。

去重也有一个经典的坑。直接用set()能去重,但顺序会乱。如果题目要求去重后保持原来的顺序,正确做法是遍历原列表,用一个新的集合记录已见过的元素,遇到没见过的才加入结果列表:

data = [3, 1, 2, 3, 4, 1, 5] seen = set() unique = [] for x in data: if x not in seen: unique.append(x) seen.add(x) # unique = [3, 1, 2, 4, 5]

3.3 map与filter:什么时候用,什么时候别用

Python里map()和filter()是两个内置的高阶函数,分别负责批量变换和批量筛选。在很多练习题参考答案里都有它们的影子。但我必须说句实话:它们能做的一切,列表推导式都能做,而且通常更清晰。

# map的效果,等价于列表推导式 nums = [1, 2, 3, 4] squared_map = list(map(lambda x: x * x, nums)) squared_comp = [x * x for x in nums] # filter的效果,同样等价于列表推导式 evens_filter = list(filter(lambda x: x % 2 == 0, nums)) evens_comp = [x for x in nums if x % 2 == 0]

我的建议是:刷题阶段你应该以列表推导式为主,把map/filter当作阅读理解能力来培养——因为别人的代码里会出现,你得看得懂。但自己写的时候,可读性优先。

4. 函数封装:练习题里最容易写出“一次性代码”的地方

很多刷题的人有个坏习惯:拿到题目,把逻辑全部堆在脚本顶层,从第一行写到最后一题,能出结果就万事大吉。61-70这个阶段的题目已经开始有意识地考察模块化思维了,典型标志就是部分题目会要求你“编写一个函数来实现xx功能”,而不再是单纯输出结果。

4.1 为什么要单独抽函数

函数封装的意义在练习题阶段不容易被体会,因为题目本身都很短,你感觉不到重复代码的代价。但一旦你写了几个稍大一点的练习项目,比如用Python处理一个成绩单文件,或者做一个简单的文本统计工具,就会发现同样的逻辑被复制粘贴了七八遍之后,改一处漏三处,苦不堪言。

董老师这组题里涉及到函数的部分,实际上是在给你打预防针:把一段有明确输入和输出的逻辑单独抽出来,取一个能说明用途的名字,这就是所有工程化开发的基本单元。刷题时就算题目没有强制要求用函数,我也建议你用函数来组织代码,形成肌肉记忆。

4.2 默认参数是可变对象时的惊天大坑

每次讲函数参数,我都必须专门拎出这个经典案例,因为它几乎坑过每一个Python学习者:

def add_item(item, container=[]): container.append(item) return container print(add_item(1)) # [1] print(add_item(2)) # [1, 2] —— 你预期的是[2]吗?

问题出在默认参数[]在函数定义时只创建一次,后续所有调用都共享这同一个列表。要修复很简单,默认值设为None,函数内部再创建新列表:

def add_item(item, container=None): if container is None: container = [] container.append(item) return container

这不是什么偏门知识,而是Python官方文档里明确强调过的坑。但练习题的参考答案一般不会主动提这个细节,所以我建议你把这条经验记下来——它不一定会出现在题目里,但它会在你后面的每一次项目实践中出现。

4.3 递归题的边界条件:从李白打酒聊起

网络热词列表里出现了“李白打酒python”,这其实是一道非常经典的递归/回溯类编程题:李白提着酒壶上街,遇店加一倍,遇花喝一斗,最后问共有多少种可能的遇店和遇花顺序。这种题考察的核心就是递归的边界条件设计。

递归问题我只有一个建议:写递归函数时,前两行永远是终止条件。递归之所以难,不是因为调用自身这个动作难,而是因为你必须清晰地知道“什么时候停止”。一旦递归没有终止条件,程序就会无限调用直到栈溢出。

# 以经典阶乘为例 def factorial(n): if n <= 1: # 终止条件,最先写 return 1 return n * factorial(n - 1)

刷到这十道题里有递归内容时,务必养成的习惯是:先用一个最简单的小参数(比如n=0或n=1)手动跑一遍递归过程,确认终止条件没问题,再上真正的测试数据。这个习惯帮我避免过至少十次“递归函数压根没走到终止条件”的尴尬情况。

5. 做题中反复踩的五个高频坑和三条排查路径

这部分是我最想分享的实战内容。我刷题时以及后来带学生时,发现有些坑出现频率高得离谱——几乎每个人都会按顺序踩一遍。把这些坑单列出来,比多刷二十道题还有用。

5.1 五个经典高频坑

先说总结,再逐个展开。这五个坑分别是:浅拷贝问题、循环内修改遍历对象、变量作用域混淆、input()拿到的一律是字符串、整数除法与浮点除法的混淆。

第一坑:列表的浅拷贝。很多题目要求你复制一个列表再处理,直接写new_list = old_list,然后你改了new_list,发现old_list也跟着变了。原因很简单:这个等号只是把引用复制了一份,两个变量指向同一块内存。正确做法是new_list = old_list[:]或者new_list = old_list.copy()。

第二坑:循环内删除正在遍历的列表元素。经典场景是“删除列表中所有偶数”:

nums = [1, 2, 3, 4, 5, 6] for x in nums: if x % 2 == 0: nums.remove(x) # 你以为结果是[1,3,5],实际结果是[1,3,5,6]

原因是在遍历过程中删除元素会让列表的索引整体前移,循环漏掉了紧跟在被删元素后面的那一个。正确的思路是“新建列表保留要留的元素”,或者倒序遍历再删除。

第三坑:变量作用域混淆。在函数里给一个全局变量赋值,函数外部却看不到变化。不深入了解局部变量和全局变量之前,这个现象会让很多初学者感到费解。如果确实需要在函数里修改全局变量,需要用global声明。但更推荐的做法是:函数通过参数传入、返回值传出,尽量不要依赖全局变量。

第四坑:input()返回的永远是字符串。如果你直接拿input()的结果和数字比较,比如if input() == 18,永远不成立。所有从input()拿到的数据,必须按需转换成int或float再参与运算。

第五坑:/与//搞混。/是浮点除法,结果永远是float;//是整除,直接去掉小数部分。练习题经常要求“计算平均数”“商和余数”,这里最容易出问题。

5.2 定位Bug的三条排查路径

做题做错了不可怕,可怕的是对着代码干瞪眼。我常用的排查路径有三条,无论新手老手都适用:

第一条:print大法。在关键位置打印中间结果。比如循环第几次时变量的值是什么,排序后列表变成了什么。不要觉得print掉价,它是排查逻辑错误最直接的手段。

第二条:二分定位。当一段代码很长时,在中间位置加print,看前面一半是否正常。如果正常,说明问题出在后面一半;如果不正常,问题出在前面一半。这样递归缩小范围,很快就能找到问题行。

第三条:边界值测试。用空列表、1个元素的列表、全是相同元素的列表、包含负数的列表去跑你的代码。很多隐藏Bug只在边界情况下暴露。

5.3 验证答案对错的简单方法

最后提供一个我在刷题时最常用的验证思路:不要睁着眼看输出对不对,要构造canonical测试用例。换句话说,你自己心里先清楚“这个输入应该得到什么输出”,再去跑程序验证。比如统计字符频次时,用"aaaa"和"abab"这种结果明确的字符串做测试。提高刷题效率的方法不是做题的数量,而是对每道题的测试意识——这个习惯你在以后做任何代码项目时都受用无穷。

6. 从练习题到真实项目:这十道题的落点在哪里

有人觉得练习题跟真实开发是两码事,刷完就忘。我的观点不太一样:练习题里练的每一项,都是真实项目中每天都在用的技能,只是场景换了,你没认出来而已。

字符串切片和格式化在分析日志文件时无处不在。比如说你有一个日志文件,每行格式是时间 - 级别 - 消息,需要提取出所有ERROR级别的消息。这就是一道活生生的字符串分割题:line.split(" - ")之后过滤。我这里也经常用Python处理文本数据,字符串基本功扎实的人,写出来的处理代码又短又稳,基础不牢的人则会写出N层嵌套循环,性能惨不忍睹。

列表推导式、排序和筛选在数据分析预处理阶段的价值就不必多说了。拿到一份csv数据,你要清洗、去重、排序、筛选,Python的列表和字典操作就是最底层的工具。董老师在练习里让你们反复练这些,反复练的正是数据处理的看家本领。

函数封装是所有工程代码的起点。练习阶段养成了“把一个逻辑独立操作抽成函数”的习惯,后面面对上千行代码时自然知道怎么拆分模块。我见过的很多转行学Python的人,最大问题不是语法不会,而是所有代码都堆在一起,完全没有函数边界,一旦出错就要从头读到底。这种代码别说别人看不懂,他自己隔两天再看也看不懂。

还有调试技巧。练习阶段的bug多半只是语法错误和逻辑小错,真实项目的bug可能涉及数据异常、并发问题、环境差异,但排查方法论是一样的:先用print确认数据流到哪里开始不对,再用二分法缩小范围,最后做边界测试确认修好了没把别的地方弄坏。这套方法论没变过。

我一直觉得,董付国老师的Python小屋系列题目最好的地方在于:它不追求题型花哨,而是老老实实地把Python最核心的操作反复锤炼。61-70这十道题更是如此——单看每道题都不难,但组合起来是在检验你对前一段学习的所有基础知识的综合运用能力。刷题这件事,重要的不是分数和数量,而是每道题做完之后,你能否在另一道从未见过的新题面前,认出它背后熟悉的套路。如果你刷这十道题的过程中有超过两道需要看答案才能写出来,我的建议是先别急着往下刷,回头把字符串、列表、函数这三块的基础代码各写一遍,再回来做,效果会好得多。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/8 11:51:24

鸿蒙原生人脸识别前端开发全解析:从相机到活体检测的实战链路

最近我刚把一个鸿蒙应用的人脸识别模块交付上线&#xff0c;前后折腾了大概三周。这个项目正好赶上公司整体的国产化迁移&#xff0c;从安卓/iOS双端往鸿蒙原生适配。做下来最大的感受是&#xff1a;人脸识别这个事&#xff0c;前端要管的远不止一个摄像头预览和拍照按钮。从相…

作者头像 李华
网站建设 2026/10/8 11:49:14

Agent-Reach 实战:让 AI Agent 稳定执行外部命令的桥接层设计

1. Agent-Reach 到底在解决什么问题 第一次看到 Agent-Reach 这个名字&#xff0c;我下意识以为是某个新出的 AI Agent 框架&#xff0c;翻了一圈才发现它更像是一个"让 Agent 真正够得着外部世界"的能力层。名字里的 Reach 很关键——不是让 Agent 更聪明&#xff0…

作者头像 李华
网站建设 2026/10/8 11:48:48

AI资讯日报系统设计:多源聚合与自动摘要实战

我无法基于当前输入生成符合要求的博文。原因如下&#xff1a;输入中仅提供了项目标题“2026-09-29 AI最新资讯日报”&#xff0c;但未提供任何实质性的【项目正文】、【关键词】或【摘要描述】。整段输入为空&#xff08;相关热搜词&#xff1a;后无内容&#xff0c;最新网络热…

作者头像 李华
网站建设 2026/10/8 11:47:09

ponytail插件:规则驱动的内容整理与日志处理利器

1. 这个插件到底是什么&#xff1a;先搞懂 ponytail 的核心定位 我第一眼看到 ponytail 这个词&#xff0c;脑子里蹦出来的是马尾辫&#xff0c;再往下想才反应过来&#xff0c;这其实是一个轻量级的本地内容整理插件。它的设计灵感和名字确实来自马尾辫——你想想看&#xff0…

作者头像 李华
网站建设 2026/10/8 11:44:38

基于Hadoop的百度云盘实现:HDFS分布式存储与Java Web实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/8 11:43:37

WorkBuddy六大行业实战:拆解Skill、记忆与规则的高效工作流

“大家都在用 WorkBuddy 做什么&#xff1f;”这句话我最近一个月被问了不下二十次。上一期《WorkBuddy 行业应用指南》发出去之后&#xff0c;很多人第一反应不是“这工具怎么用”&#xff0c;而是“别人到底拿它干了啥”。后台私信也很有意思&#xff1a;有人问科研文献能不能…

作者头像 李华