Python刷题指南:100道练习题覆盖核心知识与实战
不管是刚接触编程的大学生,还是打算转行做开发的职场新人,学 Python 时大概率都会遇到同一个尴尬阶段:看教程时觉得每行代码都认识,合上教程想独立写一个小程序,却连列表推导式都不敢下手。出现这种情况,通常不是理解力的问题,而是练习量不够。语法知识只是在脑海里发生过,还没有在手指上留下痕迹。要补上这段差距,最简单直接的办法,就是系统地刷完 100 道 Python 练习题。
这篇文章不打算堆砌概念,而是把刷题这件事拆成一条完整的学习路径:先说明为什么要练、练什么,再带你搭好练习环境,然后按照基础语法、流程控制、函数、算法与数据结构、综合小项目五个模块逐类突破。每个模块会给出典型题目、完整代码和解题思路,同时把新手最容易踩的坑单独列出来。读完之后,你可以直接照着这个节奏,每天抽出半小时,把 100 道题拆成每天的小任务,坚持二十天左右,编程手感会有非常明显的变化。
1. 为什么要刷完 100 道 Python 练习题
1.1 练习题真正的价值是什么
练习题最大的价值,不在于让你记住某个 API,而在于让你在反复编写代码的过程中,把语法规则转化成肌肉记忆。比如range、append、join这类高频方法,第一次使用可能还要翻文档,独立写十几遍之后,基本可以做到不假思索。这种内化过程,只能靠大量练习完成。看教程时产生的“我懂了”容易造成一种假象,真正能判断自己是否掌握的,是你能不能在不看参考答案的情况下,把一个空白的.py文件写满可以运行的代码。
刷题还能帮你尽早暴露问题。语法错误、边界条件、逻辑漏洞、变量命名混乱,这些在阅读时根本察觉不到,只有亲手运行代码,让解释器把错误信息抛到脸上,你才会真正意识到自己的薄弱点。很多开发者回想自己入门最快的阶段,往往不是听课最认真的时候,而是每天写代码练手最频繁的那段时间,原因就在这里。
1.2 100 道题应该覆盖哪些知识点
一套合格的 Python 练习题,不能只停留在“输出九九乘法表”这种单一句法层面,而是要覆盖日常开发最常用的能力。按照我整理题目的经验,可以把 100 道题大致分成五个模块:基础语法与数据类型约占两成,包括数值运算、类型转换、字符串处理、列表与字典操作;流程控制约占两成,重点是分支判断、循环嵌套、穷举逻辑;函数与模块化约占两成,包括参数传递、返回值、Lambda、装饰器和递归;算法与数据结构约占两成,涉及排序、查找、栈与队列思想的简单实现;最后两成留给综合小项目,比如文件统计、猜数字、CSV 读写这类能立刻看到效果的练习。
这样的分布和实际开发中用到的知识点重合度很高。很多教程只讲语法,但工程里真正高频使用的能力,恰恰是“把问题拆成函数”“用循环遍历数据”“用字典完成计数”这些基本功。100 道题练完,并不是说能背下多少代码,而是遇到需求时,你能自然想到用哪种语法结构去实现。
1.3 每天一练的节奏应该怎么安排
我给这套题设计的刷题节奏是“少量多次”,而不是周末集中练一整天。每天留出 30 到 45 分钟,完成 3 到 5 道题,难度可以循序渐进。前十天做基础语法和简单流程控制,中间十天进入函数与数据结构,最后一周集中完成综合项目。每道题先独立思考十五分钟,卡住了再看参考答案,看懂之后合上答案,自己重新完整写一遍,这比盯着别人的代码抄十遍效果要好得多。
这里还要提醒一点:刷题不是比赛谁写得快,而是追求写的每一步都有依据。完成一道题之后,可以反问自己三个问题:这个解法能不能处理边界情况?有没有更简洁的写法?如果换一组数据,这段代码还会不会出错?带着这三个问题去做题,每一道题才能练出真正的价值。
2. 环境准备:搭好 Python 练习环境
2.1 Python 解释器怎么安装
刷题离不开一个能运行代码的环境。Windows 用户直接到 Python 官网下载最新的 3.x 安装包,安装时记得勾选 “Add Python to PATH”,否则后续在命令行敲python会提示找不到命令。安装完成后,按Win + R输入cmd打开命令行,执行下面这条命令验证版本:
python --version如果输出类似Python 3.12.x的信息,说明安装成功。如果你使用的是 Linux 系统,很多发行版会自带 Python 3,可以用系统包管理器安装:
sudo apt update && sudo apt install python3macOS 用户同样可以安装官方安装包,或者使用 Homebrew,安装完成后在终端测试python3 --version。这里要注意一个小陷阱:部分系统上python命令可能指向 Python 2,所以建议统一使用python3命令,或者确认python指向的是 3.x 版本。如果你选择安装 Anaconda,环境变量和包管理都会被一并处理,对数据分析和后期做练习题也会方便很多。
2.2 编辑器或 IDE 怎么选
练习代码不一定要一上来就装重型 IDE,但一个好的编辑环境能减少很多无谓的折腾。新手我比较推荐 VS Code,免费、轻量、插件生态完善。安装 VS Code 后,在扩展商店搜索 “Python”,安装微软官方提供的 Python 扩展,它会自动识别你电脑上的解释器,并提供代码补全和错误提示。打开命令面板,选择Python: Select Interpreter,指定刚才安装的那个解释器即可。
如果你更喜欢一切配置都帮你搞定的开发环境,PyCharm 的 Community 版本也完全够用。新建项目时选择New environment,PyCharm 会自动创建虚拟环境,省去了手动配置的麻烦。不过对于刷练习题这样的小脚本,VS Code 有时候反而更轻快,打开文件直接运行,不需要等待整个项目索引。不管用哪个编辑器,请务必确保右下角或状态栏里显示的解释器版本和实际安装版本一致,很多“代码明明没问题却运行报错”的情况,最后发现都是解释器选错了。
2.3 练习项目的目录结构
刷题虽然是一个个小脚本,但也值得用工程化的方式组织文件。建议在本地建立一个统一的练习目录,比如python-100-practice,然后按日期或主题分子目录存放题目:
python-100-practice/ ├── day01_basic/ │ ├── 01_type_conversion.py │ └── 02_string_operation.py ├── day02_control/ │ ├── 03_prime.py │ ├── 04_multiplication_table.py │ └── 05_hundred_chicken.py ├── data/ │ └── sample.txt └── README.md每个文件只放一道题的解法,文件名用数字编号加上简短描述。这样二十天下来,你能清楚看到自己练了多少题,也方便之后复盘。README 文件可以记录每天的完成情况和遇到的报错,别小看这个习惯,很多人在刷到第 60 题时突然忘记前面学过什么,回头看这种笔记往往能快速唤醒记忆。
3. 基础语法篇:数据类型与运算
3.1 数值运算与类型转换
基础语法是整套题的地基。第一类练习围绕数值运算和类型转换展开,别觉得简单,很多进阶问题比如“商和余数”“浮点数精度”都藏在这里。下面是一个最常见的练习:定义两个变量,计算它们的和、差、积、商、整除结果、余数和幂。
a = 10 b = 3 print(a + b) # 13 print(a - b) # 7 print(a * b) # 30 print(a / b) # 3.3333333333333335 print(a // b) # 3 print(a % b) # 1 print(a ** b) # 1000这段代码的重点在于理解/和//的区别:前者是浮点数除法,哪怕能整除也会返回浮点数;后者是整除,只会保留整数部分。%是取余数,在判断奇偶、判断能否整除、日期计算中非常常用。类型转换则是另一个高频考点,int("42")可以把数字字符串转成整数,float("3.14")转成浮点数,str(100)把数字转成字符串。刷题时经常遇到TypeError,就是因为把字符串和数字直接做了加法运算。
3.2 字符串处理
字符串处理是 Python 入门阶段性价比最高的练习主题,因为爬虫、数据分析、日志处理都会用到。常见的练习题包括字符串翻转、大小写转换、分割合并、统计字符出现次数。下面给出一个回文判断的经典实现:
def is_palindrome(text: str) -> bool: text = text.lower() return text == text[::-1] print(is_palindrome("level")) # True print(is_palindrome("Python")) # False print(is_palindrome("上海自来水来自海上")) # Truetext[::-1]是切片操作的逆序写法,短短一行代码就完成了字符串反转。lower()的作用是把大写统一转成小写,避免Level和level被判定成不同字符。除了解法本身,这道题还训练了函数封装能力:把判断逻辑包在is_palindrome里,返回布尔值,调用方只需要关注True或False。练习字符串时,还要熟悉split()、join()、replace()这几个方法,它们几乎是所有文本处理题目的基础工具。
3.3 列表与去重
列表是 Python 里使用频率最高的容器类型之一。关于列表的练习,可以从增删改查开始,逐步过渡到去重、排序、统计频次。下面是一道常见的列表去重题:
nums = [1, 2, 2, 3, 4, 4, 5, 5, 5] unique = list(set(nums)) print(unique) # 输出顺序不固定,例如 [1, 2, 3, 4, 5] # 如果需要保持原有顺序,可以这样写 seen = set() result = [] for num in nums: if num not in seen: result.append(num) seen.add(num) print(result) # [1, 2, 3, 4, 5]第一种写法利用集合天然去重的特性,代码最简洁,但输出顺序不一定稳定,因为集合是无序的。第二种写法用set充当“已出现元素”的登记表,再遍历原列表,这样既能去重又能保持元素第一次出现的顺序。这两种思路在实际开发中都有应用场景:只看重结果是否去重时用第一种,需要保留顺序时用第二种。刷这道题时,还可以顺手练习字典的fromkeys方法,这也是一种常见的去重写法。
4. 流程控制篇:循环与条件判断
4.1 素数判断
流程控制是编程逻辑的核心,它决定了代码在什么条件下做什么事。素数判断几乎是每一套 Python 练习题都会收录的题目,因为它同时考察了循环范围、条件判断和数学优化三个知识点。基础版实现如下:
def is_prime(n: int) -> bool: if n < 2: return False for i in range(2, int(n ** 0.5) + 1): if n % i == 0: return False return True for n in range(1, 30): if is_prime(n): print(n, end=" ")很多人第一次写这个函数,会把循环范围写成range(2, n),功能上没错,但当 n 很大时效率不高。实际上如果 n 有因子,那么一定有一个因子不大于它的平方根,所以只需要检查到int(n ** 0.5)即可。这个优化思路以后在算法题里会反复出现。另外,n < 2的边界判断一定要写,1 不是素数,这属于经典易错点。学习流程控制时,不要只看循环怎么转,更要学会分析循环的终止条件和边界情况。
4.2 九九乘法表
九九乘法表是一道看起来简单、实际上很考验循环嵌套和输出格式的题目。很多新手会把内层循环写成range(1, 10),结果输出的是完整的九行九列,而不是下三角形状。正确的做法是用外层循环控制行数,内层循环的上限由外层的当前值决定:
for i in range(1, 10): for j in range(1, i + 1): print(f"{j} * {i} = {i * j:<4}", end=" ") print()这里的两个关键点在于:内层循环用range(1, i + 1),保证每行只输出到当前行号对应的列,形成下三角效果;end=" "让每次print后不换行而是输出空格;print()在外层循环中执行,负责一行结束后的换行。格式化字符串里的:<4表示左对齐并占 4 个字符宽度,可以让输出对齐得更整齐。这道题虽然简单,但如果你能独立把它写出来,说明你已经理解了循环嵌套的执行顺序。
4.3 百钱买百鸡
百钱买百鸡是我国古代数学家提出的经典问题:公鸡 5 文钱一只,母鸡 3 文钱一只,小鸡 1 文钱三只,用 100 文钱买 100 只鸡,问公鸡、母鸡、小鸡各多少只。这道题非常适合训练穷举思想,核心是循环遍历所有可能的组合,再用条件过滤出满足条件的组合:
for x in range(0, 21): # 公鸡最多买 20 只 for y in range(0, 34): # 母鸡最多买 33 只 z = 100 - x - y # 小鸡数量由总数决定 if z >= 0 and z % 3 == 0 and 5 * x + 3 * y + z // 3 == 100: print(f"公鸡 {x} 只,母鸡 {y} 只,小鸡 {z} 只")循环上限不是随便写的:公鸡 5 文钱一只,最多买 20 只,所以range(0, 21);母鸡 3 文钱一只,最多买 33 只,所以range(0, 34)。条件判断里z % 3 == 0必须加上,因为小鸡是 3 只 1 文钱,只有数量是 3 的倍数时,价格才可能是整数。这道题的难点不在语法,而在如何把数学条件翻译成代码逻辑,这也是后续做算法题的基本功。运行后可以输出四组解,你可以自己验证一下结果是否正确。
5. 函数篇:把逻辑封装成可复用代码
5.1 递归实现阶乘
函数是 Python 组织代码的基本单位。当程序需要重复完成某段逻辑时,把它封装成函数能显著提高可读性和复用性。阶乘是理解递归最好的入门题:n! = n * (n-1)!,递归函数就是在函数内部调用自身。实现如下:
def factorial(n): if n <= 1: return 1 return n * factorial(n - 1) print(factorial(5)) # 120 print(factorial(10)) # 3628800递归最核心的是两个部分:递归结束条件和递归调用。if n <= 1就是结束条件,防止函数无限调用下去;n * factorial(n - 1)是递归调用,每次把问题规模缩小 1。理解递归时,不要试图在脑子里一步步展开所有调用过程,只要确认“当前层的结果依赖下一层的结果,下一层逻辑与当前层完全一致”就足够了。这也是后续学习树、图的深度优先遍历等算法时会反复用到的重要思想。递归虽好,但要注意递归深度,Python 默认递归深度限制约 1000 层,写递归前要想清楚数据规模。
5.2 Lambda 表达式与排序
Lambda 表达式是 Python 中快速定义小型匿名函数的方式,特别适合作为sort、sorted、map、filter等函数的参数。下面是一个常见的练习:按学生成绩从高到低排序,然后按姓名排序。
students = [ ("Zhang", 85), ("Li", 92), ("Wang", 78), ("Zhao", 92), ] students.sort(key=lambda item: item[1], reverse=True) print(students) students.sort(key=lambda item: item[0]) print(students)key参数接收一个函数,这个函数从每个元素中提取用于排序的键。lambda item: item[1]表示取元组的第二个元素,也就是成绩;reverse=True表示降序。第一段输出会按成绩从高到低排列,第二段会按姓名升序排列。Lambda 表达式虽然简洁,但也别滥用,如果逻辑超过一行,或者需要在多处复用,就应该定义普通函数。这道题的价值在于让你理解“函数可以作为参数传递”这一概念,它也是了解装饰器和回调函数的基础。
5.3 装饰器计算函数耗时
装饰器是 Python 进阶的一个重要特性,它允许在不修改原函数代码的前提下,为函数增加额外的功能。最常见的练习是写一个计时装饰器,统计目标函数运行了多长时间:
import time def timer(func): def wrapper(*args, **kwargs): start = time.time() result = func(*args, **kwargs) print(f"{func.__name__} 运行耗时 {time.time() - start:.6f} 秒") return result return wrapper @timer def sum_to_n(n): return sum(range(n + 1)) print(sum_to_n(1000000))装饰器timer接收一个函数,返回一个新的wrapper函数。wrapper内部先记录开始时间,再调用原函数,调用结束后打印耗时,最终返回原函数的结果。@timer语法糖等价于sum_to_n = timer(sum_to_n)。理解装饰器的关键是抓住“闭包”这个概念:内层函数wrapper可以访问外层函数timer的参数func,即使外层函数已经返回,这种访问仍然有效。刷到这道题时,如果第一次看不太懂,可以先放一放,等函数和闭包的概念更扎实后再回来看,效果会更好。
6. 算法与数据结构篇:排序与查找
6.1 冒泡排序
算法是编程的内功,排序则是算法里最经典的主题。冒泡排序的原理是通过相邻元素两两比较,把较大的元素逐渐“冒泡”到数组末尾。实现如下:
def bubble_sort(arr): n = len(arr) for i in range(n - 1): swapped = False for j in range(n - 1 - i): if arr[j] > arr[j + 1]: arr[j], arr[j + 1] = arr[j + 1], arr[j] swapped = True if not swapped: break return arr nums = [64, 34, 25, 12, 22, 11, 90] print(bubble_sort(nums))这里有两个容易理解错的地方。第一,外层循环每走一轮,就会把当前未排序部分的最大值放到最后,所以内层循环的上限是n - 1 - i,避免对已经就位的元素再做无意义比较;第二,swapped是一个优化标记,如果某一轮循环没有任何交换,说明数组已经有序,可以直接跳出,这在数据接近有序时能省下大量时间。刷排序题时,不建议追求背代码,而是要在纸上画一遍元素交换的过程,真正理解每一行代码在做什么。学会冒泡排序后,可以继续尝试插入排序、选择排序,最终接触快速排序和归并排序。
6.2 二分查找
查找是算法里另一类基础问题。二分查找要求待查找的数组必须有序,它的核心思想是每次把搜索范围缩小一半,时间复杂度是 O(log n),比逐个遍历的线性查找高效得多。经典实现如下:
def binary_search(arr, target): left, right = 0, len(arr) - 1 while left <= right: mid = (left + right) // 2 if arr[mid] == target: return mid elif arr[mid] < target: left = mid + 1 else: right = mid - 1 return -1 nums = [1, 3, 5, 7, 9, 11, 13] print(binary_search(nums, 7)) # 3 print(binary_search(nums, 6)) # -1这道题最典型的坑是边界条件。while left <= right里的等号不能丢,否则当搜索区间只剩一个元素时可能漏判;left = mid + 1和right = mid - 1的加减 1 也不能省,否则可能出现死循环。建议刷完基本版之后,再尝试两种变体:查找第一个等于目标值的位置、查找最后一个等于目标值的位置。这两种变体在 LeetCode 上非常常见,也是面试常考的二分查找边界问题。二分查找虽然代码不长,但能把边界条件想清楚,说明你的逻辑能力已经上了个台阶。
6.3 斐波那契数列生成
斐波那契数列是递归、循环、动态规划都能覆盖的经典题目,一套题里至少会出现两次。第一次要求用循环输出前 N 项,第二次要求用递归实现第 N 项的值。先看循环版本:
def fibonacci(n): a, b = 0, 1 result = [] for _ in range(n): result.append(a) a, b = b, a + b return result print(fibonacci(10)) # [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]a, b = b, a + b这行代码同时完成两个赋值,等号右边的值会先计算完,再整体赋给左边,所以不需要引入临时变量。这个写法非常 Pythonic,在很多场景下都能用。再看递归版本的实现:
def fib_recursive(n): if n <= 1: return n return fib_recursive(n - 1) + fib_recursive(n - 2) print(fib_recursive(10)) # 55递归版本虽然简洁,但存在大量重复计算,当 n 变大时性能会急剧下降。刷到这道题时可以思考一个问题:之前写过的哪个装饰器能让递归斐波那契不重复计算?答案是加一个缓存装饰器。到这一步,你会把装饰器、递归、算法优化这几个知识点真正串起来,这种知识之间的连接,正是刷题最有价值的地方。
7. 综合实战篇:文件操作与小游戏
7.1 统计文件单词频率
当基础语法和函数都练得差不多时,就可以进入综合实战了。文件操作和字符串处理结合起来,最常见的题目是统计文本中每个单词出现的次数。为了保证代码可以直接运行,先创建一个示例文本文件:
sample = """Python is easy to learn. Python is powerful. Practice makes perfect. """ with open("sample.txt", "w", encoding="utf-8") as f: f.write(sample)然后编写统计代码。这里用到了collections.Counter和正则表达式,前者是一个专门用于计数的容器,后者用来从文本中提取英文单词:
from collections import Counter import re def count_words(file_path): with open(file_path, "r", encoding="utf-8") as f: text = f.read() words = re.findall(r"[a-zA-Z']+", text.lower()) return Counter(words) counter = count_words("sample.txt") for word, cnt in counter.most_common(5): print(f"{word}: {cnt}")运行后会输出python: 2、is: 2、easy: 1这样的统计结果。这道题的亮点在于把好几个知识点串在了一起:open的上下文管理器写法with ... as f,可以确保文件用完后自动关闭;text.lower()把大写统一转成小写,避免Python和python被当成两个词;Counter.most_common(5)直接返回出现次数最多的前五个单词。做完这道题,你其实已经掌握了一个简易词频统计工具的核心逻辑,后续做数据分析、文本挖掘时思路也会更清晰。
7.2 猜数字小游戏
猜数字小游戏是综合实战里最受欢迎的一道题,因为它有交互、有随机数、有异常处理,能模拟真实程序的完整运行流程。游戏规则是程序随机生成一个 1 到 100 之间的整数,玩家通过输入猜测,程序提示猜大还是猜小,直到猜对为止:
import random secret = random.randint(1, 100) guess_count = 0 print("猜数字游戏开始!范围是 1~100") while True: try: guess = int(input("请输入你猜的数字: ")) except ValueError: print("输入不合法,请输入整数") continue guess_count += 1 if guess < secret: print("猜小了") elif guess > secret: print("猜大了") else: print(f"恭喜!你一共猜了 {guess_count} 次") break这道题最容易忽略的地方是try...except。如果不处理异常,玩家输入一个非数字内容时程序会直接崩溃,而不是友好地提示重新输入。continue的作用是跳过本次循环的后续代码,直接进入下一轮输入。guess_count用来记录猜测次数,这也训练了计数变量的使用。运行这个游戏,你会第一次体会到“程序在和人交互”的乐趣。做完基本版之后,还可以自己加需求:限制最多猜 7 次,猜不到就提示失败;或者统计玩家历史最好成绩。这种自己给自己提需求的能力,比单纯照抄题目有价值得多。
7.3 CSV 文件读写
实际开发中,数据经常以 CSV 格式存储,学会读写 CSV 是非常实用的技能。下面这道练习要求把学生成绩写入scores.csv,再读取并逐行打印:
import csv data = [ ["name", "score"], ["Zhang", 85], ["Li", 92], ["Wang", 78], ] with open("scores.csv", "w", encoding="utf-8", newline="") as f: writer = csv.writer(f) writer.writerows(data) with open("scores.csv", "r", encoding="utf-8") as f: reader = csv.reader(f) for row in reader: print(row)写入时必须指定newline="",否则在 Windows 平台上生成的 CSV 文件会在每行之间多出空行,这是一个非常经典的坑。写入时writer.writerows(data)接收一个二维列表,一次性写入多行;读取时csv.reader返回一个迭代器,每次迭代得到一行数据组成的列表。刷这道题时,可以试着用字典形式存储成绩,再使用csv.DictWriter和csv.DictReader,它们用列名而不是下标来访问数据,代码可读性会更高。掌握 CSV 读写之后,你再去看数据分析相关的案例,会发现很多项目的第一步就是“读入 CSV 文件”。
8. 刷题高频报错与排查思路
8.1 高频报错对照表
刷题过程中报错是常态,不要怕报错,反而要感谢报错信息,因为它直接告诉你问题出在哪里。下面整理了新手刷题时最常遇到的几类错误:
| 报错信息 | 常见原因 | 解决思路 |
|---|---|---|
IndentationError | 缩进不一致,混用 Tab 和空格 | 统一用 4 个空格缩进 |
SyntaxError | 中文标点、括号不匹配、缺少冒号 | 检查代码编辑器中的高亮位置 |
NameError: name 'x' is not defined | 变量名拼写错误或未定义 | 检查变量前后是否同名 |
TypeError: unsupported operand type(s) | 不同类型之间做了运算,比如字符串加数字 | 使用int()、str()做类型转换 |
IndexError: list index out of range | 列表下标越界 | 检查len()长度,注意下标从 0 开始 |
KeyError: 'key' | 字典中不存在该键 | 使用dict.get(key, 默认值) |
FileNotFoundError | 文件路径不存在 | 先确认当前目录,再检查文件名大小写 |
RecursionError | 递归没有结束条件或递归层数过深 | 检查递归基线条件,考虑改用循环 |
这张表里的错误,几乎每一个都是编程新手一定会踩的坑。建议把这张表复制到你的 README 文件里,遇到报错先按表格对号入座,比直接去搜索引擎复制粘贴更高效。尤其是IndexError和KeyError,它们频繁出现的原因是很多新手对“下标从 0 开始”和“字典键不存在”这两个概念不够敏感,多做几道列表和字典相关的题目就能逐渐适应。
8.2 一个典型的排查流程
当报错不在上表时,可以按下面的顺序排查。第一步,仔细阅读报错信息最后一行,它通常会说明错误类型和出错的文件名、行号;第二步,检查出错那一行代码,优先看变量名、函数名是否拼写正确,标点是否为英文半角;第三步,在关键位置加print(),把变量值打印出来,确认数据是否符合预期;第四步,如果数据没问题,再检查逻辑边界,比如循环有没有越界、条件判断有没有覆盖到空列表。这里要特别强调print()调试法,很多新手一遇到问题就想用复杂的调试工具,其实在刷题阶段,print是最快、最直观的定位手段。
给你一个真实场景:假设你运行词频统计代码时报了FileNotFoundError,不要急着改代码,先执行pwd或os.getcwd()查看当前工作目录,再确认sample.txt是否真的在这个目录下。很多时候,文件明明存在却报错,只是因为启动脚本的目录不对。这种排查思路本身就是刷题要练的软技能,你越早学会系统排查,后面做项目时就越少被环境问题卡住。
9. 高效刷题的最佳实践
9.1 先写思路再写代码
很多新手刷题的通病是拿到题目马上敲代码,敲到一半发现逻辑不对,又全部删掉重来。更高效的做法是先花两分钟在纸上写出思路,哪怕只是“先循环遍历所有数字,判断条件,再打印符合条件的值”这一步口语化的描述也行。思路写清楚之后,代码会自然很多。比如百钱买百鸡这道题,如果你事先写下“用两层循环穷举公鸡和母鸡数量,小鸡数量用总数减去前面两个数,再判断钱数是否等于 100”,代码写起来几乎不会卡壳。刷题训练的不只是写代码,更是拆解问题的能力,这种能力只能通过“先想后写”的练习方式培养。
9.2 注意边界条件和代码规范
刷题时还要养成检查边界条件的习惯,这是区分“能跑”和“写得好”的分水岭。判断素数的函数要处理n < 2的情况,二分查找要注意left <= right的等号,列表去重要考虑空列表和全相同元素的极端输入。边界条件看似只是几个额外的判断,但实际项目中绝大多数 bug 都发生在边界情况。与此同时,代码规范也要从第一道题开始养成:变量名使用有意义的英文单词而不是a、b、c;函数名用动宾结构比如get_average、is_prime;关键逻辑处加上简短注释。这些习惯入门时不养成,后面在代码量变大的项目中会很痛苦。
9.3 记录错题与复盘
刷题不是做完了就结束,复盘是提升最快的环节。建议每完成 5 道题,花十分钟翻看之前的代码,问自己三个问题:有没有哪道题的解法还能简化?有没有哪类错误反复出现?有没有哪个知识点理解得还不够透?把反复犯的错误记在 README 里,比如“总是忘记字符串下标从 0 开始”“列表推导式里把 if 的位置写错”,一周之后回头来看,你会发现自己重复踩坑的次数在明显减少。
这里还要推荐一个进阶做法:每道题至少写出两种解法。比如去重题先用set写一遍,再用循环保持顺序写一遍;排序题先写冒泡排序,再调用内置sorted对比两种方式的差异。写第二遍时,你会被迫思考不同写法的优缺点,这种对比训练对编程思维提升非常有帮助。100 道题如果平均每道题产生两版代码,你实际上练了 200 次独立的编码过程,效果自然不一样。
10. 100 题之后怎么继续提升
刷完 100 道题,你已经初步具备了独立编写小脚本的能力,但这也只是 Python 学习的起点。接下来可以根据兴趣选择方向:想往数据处理方向发展,可以学习 NumPy、Pandas,把 Python 数据分析与可视化的技能树补全,用真实数据集做统计分析和图表展示;对自动化感兴趣,可以练习用 Python 写批量文件处理脚本,或者把写好的练习脚本打包成 exe 文件发给朋友使用;想做网络方向,可以先学习 requests 和 BeautifulSoup,从简单的爬虫入门,再逐步理解 HTML 结构和反爬机制。还有一些方向比如量化交易策略、Web 开发、自动化测试,都是 Python 生态里非常成熟的领域,选择任何一个深入下去都很有前景。
不过要提醒一点:不要刷完 100 题就陷入“什么方向都想看,什么方向都只看了两眼”的状态。无论选择哪个方向,都建议用项目驱动的方式继续练习,比如自己定一个“做一个命令行版的记账工具”这样的目标,然后用 Python 逐步实现。你会发现,做真正的小项目和刷练习题是两种完全不同的体验,前者会逼你去查询文档、拆分功能、处理异常,这种真实场景中的解决问题能力,才是从“会做题”迈向“会开发”的关键一步。
练题最忌讳的是三天打鱼两天晒网。每天固定半小时,哪怕只完成两道题,坚持一个月,效果一定比周末一次性刷二十道题好得多。等你能在不看参考答案的情况下,独立完成一道综合题目,并且知道自己为什么这样写的时候,你的 Python 已经不是刚入门时的水平了。收藏这篇文章,从第一道题开始,把你自己的python-100-practice目录建起来,二十天后再回来看,你会感谢现在开始的自己。
