简介面向Python初学者的100道经典练习题PDF适合零基础或刚入门的学习者通过实例强化语法与编程思维。题目覆盖循环与条件、函数与模块、递归、列表/字符串处理、矩阵运算、排序算法及时间文件操作等核心主题并收入数字组合、个税计算、水仙花数、斐波那契数列、杨辉三角等经典题目每题配有题目、程序分析及参考代码按从易到难编排可作课后练习或考前刷题手册。资源为单个PDF文件约139KB内含100道实例及完整目录便于快速定位检索当前已有1466人学习配套知识点说明清晰适合自学或教学辅助。通过逐题练习读者能扎实掌握Python基础语法、常用内置模块与常见算法思路部分题目附带多种解法或拓展思路便于对比掌握为后续爬虫、数据分析或Web开发等方向打下坚实基础。1. 一百道旧题为什么还能当 Python 基础训练主餐很多人看到“Python100道经典练习题建议收藏”这种文档资料第一反应都是丢进收藏夹吃灰。我一开始也这样直到用它带过几个从零开始的同事才发现这套题的目录顺序是有讲究的从实例001的三位数字组合到实例038的矩阵对角线之和再到实例099的磁盘读写走完一遍刚好覆盖入门到进阶的主干语法。它没有花哨的项目背景每道题都能单独跑、能改参数、能立刻看到输出非常适合“写代码找手感”这个阶段。不管你是刚学完循环的新手还是想在面试前快速过一遍基础这套题都能当 checklist 用。下面我按照实际刷题顺序把它拆开。2. 题号背后的知识点地图先拆目录再动手2.1 从001到100题目顺序藏着三层递进这套 100 道题最容易被忽略的是它的编号顺序。目录里实例001到实例100看起来只是题目堆叠实际上可以分成三段。前 35 道聚焦基础语法实例001 数字组合、实例002 个税计算、实例004 日期判断、实例005 三数排序练的是输入输出、循环嵌套、条件分支。36 到 60 开始加入算法和位级操作实例036 算素数、实例037 排序、实例038 矩阵对角线之和、实例051-055 位运算。61 以后进入应用层实例061 杨辉三角、实例072 创建链表、实例091-096 time 模块、实例097-099 磁盘读写。这个排列不是巧合它正好符合“能跑脚本 → 能拆结构 → 能写应用”的学习路径。我建议你不要从中间抽题。很多新人拿到题目先挑会做的结果刷到第80题时发现自己递归和类都没练过。按编号顺序刷你会在前35道里反复使用 print、input、range36到60要求你把这些语句组合成排序、矩阵、位运算逻辑61以后要求你主动查time模块的函数、理解文件对象。每一段都在复用前一段的产出跳到后面再回来反而别扭。实际操作时我一般会把题目分成三组1-40、41-80、81-100。第一组要求能默写出大多数答案第二组要求能讲清楚为什么第三组要求能自己扩展。分组之后每天的刷题量就有了边界不会出现“今天想刷5道结果被一道递归卡了整个下午”的情况。这种训练方式跟做项目不一样。项目练的是把多个知识点组装起来而这里的每一道题只考核一到两个知识点出了问题容易定位答案不对要么循环边界错了要么条件判断写反了。对新手来说这种“黑匣子很小”的题目特别重要因为你不需要在一千行代码里找 bug只看几行就能定位。对熟手来说100 道题里总有那么几道冷门题比如位运算的按位取反、time 模块的格式化能帮你补上平时用不到的知识盲区。2.2 十类主题对应表哪里薄弱就刷哪里为了让你快速定位薄弱项我把100道题整理成一张知识点对照表。这张表不是目录的复述而是按“练习目的”重新分类知识点实例区间核心练习内容建议优先级循环与条件001-006、011、012数字组合、个税区间、兔子数列必练数学与数论003、013-015、019、025完全平方数、水仙花、质因数、完数必练字符串处理017、018、030-033、060、079回文、字符串相加、列表转字符串必练递归与递推011、020、021、024、026-028斐波那契、猴子偷桃、阶乘、等差数列重点排序与列表005、037、039-040、066-068、074三数排序、插入元素、逆序、旋转重点矩阵运算038、044对角线之和、矩阵相加重点位运算051-055按位与或非、取反、移位选练面向对象041-043、087类方法与变量、作用域、访问成员重点时间处理009、010、016、091-096time 模块、日期格式、暂停输出重点文件读写097-100磁盘写入、读写、列表转字典必练这张表里最难归类的是矩阵运算。实例038 和实例044 在目录里只占两题但它们练的是二维列表的下标控制。主对角线的规律是行号等于列号副对角线是行号加列号等于 n-1这两个规律不亲手写一遍很难建立直觉。所以我更愿意把它归到“重点”而不是“选练”。另外值得注意这套题的主体是一份 PDF 文档资料题目列表甚至在文件里就是纯文本目录。好处是复制代码方便坏处是某些题没有提供标准答案只有程序分析。遇到这种情况我的做法是先抄一遍代码然后用第4章说的断言方法验证输出而不是只看答案。如何用这张表我的习惯是先定一个目标比如“我想练好递归”就在表里找到递归对应的实例011、020、021、024、026-028集中刷这六道题。刷完再回到编号顺序接着走。这样既保留了编号顺序的递进关系又能在专项上做突破。2.3 哪些题能跳哪些题建议必刷如果时间不够至少有35道必练。我的必练清单是001、002、004、006、008、011、012、013、014、019、020、021、024、026、027、028、030、033、036、038、039、044、051、052、053、054、055、061、074、091、092、093、094、095、097、098、099。这些题覆盖了循环、条件、递归、列表、字符串、位运算、面向对象、时间、文件练完它们Python 基础语法就算过了一遍。剩下的题也不是随便跳。比如画菱形、画椭圆、画矩形这类 turtle 图形题它的知识核心是明白坐标和角度逻辑上没有新东西。我的建议是跑一遍看效果就行不用死磕算法。比如实例059 直接叫“画图丑”这道题的价值就在于让你体验把数学坐标变成图形输出感受一下库的调用方式。如果你连看哪些题都嫌麻烦可以用一个很短的路径做体验从001、005、008、014、038、097 这六道题按顺序跑一遍。这六道覆盖了循环、排序、乘法表、质因数分解、矩阵、文件基本就是全书的骨架。“可跳”不代表“不用做”。我见过不少人跳过图形题结果后面实例064、065画椭圆和矩形组合时完全不知道从哪下手。图形题的正确打开方式是先跑源代码再改几个参数看形状变化最后再自己默写一遍。整个过程不会超过15分钟。3. 核心题型拆解循环、递归、字符串、类与矩阵的代码模式3.1 循环与条件数字组合和个税计算为什么要嵌套先看实例001的数字组合。这个题要求用 1、2、3、4 组成互不相同且无重复数字的三位数最直接的做法就是三层循环total 0 for i in range(1, 5): for j in range(1, 5): for k in range(1, 5): if i ! j and j ! k and i ! k: print(i, j, k) total 1 print(总数:, total)逻辑说明range(1,5)生成 1 到 4左闭右开这是初学容易混的第一点三层循环把所有百位、十位、个位的组合都列出来i ! j and j ! k and i ! k同时保证三位互不相同。输出结果是 24。如果换用itertools.permutations([1,2,3,4], 3)一行就能拿到所有排列适合在知道自己思路正确后简化代码。参数说明这里的固定数字 1 到 4 是写死的如果想改成 1 到 6只需要把三个range的参数都改成range(1,7)。我一般会鼓励新人把这个参数提取成变量digits range(1,5)这样改起来不会漏。再看出现在实例002的个税计算它比数字组合更考验区间划分能力。原题按利润分六个档位每档提成比例不同。常见写法是用两个平行列表profit int(input(利润: )) bonus 0 limits [100000, 100000, 200000, 200000, 400000] rates [0.1, 0.075, 0.05, 0.03, 0.015, 0.01] for i in range(len(limits)): if profit limits[i]: bonus profit * rates[i] profit 0 break else: bonus limits[i] * rates[i] profit - limits[i] bonus profit * rates[-1] print(bonus)逻辑说明limits和rates是两个平行列表limits存每个区间的长度例如第一个区间 10 万按 10%第二个区间 10 万按 7.5%第三、四个区间都是 20 万第五个 40 万。循环从左往右扣区间扣不完的剩余部分最后按最高的 1% 兜底。这是我见过最精简的写法坏处是第一次读很难看懂所以刷题时我建议先写最笨的 if-elif 版本能跑通再改成这个版本。参数说明把profit改为浮点数输入代码依然有效因为 Python 的数值比较和乘法都支持浮点。如果希望税率或区间可调整把limits和rates提到函数参数里即可。3.2 递归与递推斐波那契、猴子偷桃和阶乘的边界条件递归题在整套题里占了不小比例实例011养兔子、实例021猴子偷桃、实例024斐波那契II、实例026递归求阶乘、实例028递归求等差数列核心其实都是同一个套路先写终止条件再写递推公式。以斐波那契为例def fib(n): if n 1: return n return fib(n - 1) fib(n - 2)逻辑说明终止条件是 n0 或 n1直接返回 n递归式是前两项之和。这段代码看起来干净但求 fib(35) 会明显卡顿因为同一子问题被反复计算。改进方法是用缓存装饰器from functools import lru_cache lru_cache(maxsizeNone) def fib(n): if n 1: return n return fib(n - 1) fib(n - 2)参数说明maxsizeNone表示不限制缓存条数也可以手动写字典存结果。刷题时如果碰到实例026 递归求阶乘、实例027 递归输出、实例028 递归求等差数列边界条件的写法都类似先写终止条件再写递推公式。猴子偷桃实例021其实不适合递归更适合反向递推从第10天剩下1个桃逆推出第1天的桃子数。很多人被“递归”两个字带偏非要用递归结果写出一堆状态。我的建议是先判断问题是否天然具有“调用自身”的结构如果没有就老老实实用循环。实际刷题时可以做一个对比实验用普通递归和带lru_cache的递归分别跑 fib(30)观察耗时差距。这个实验做完你对“重复计算”这个概念的感受会非常直观。3.3 字符串与列表回文、join 和复读机相加实例030回文数、实例031字母识词、实例033列表转字符串、实例079字符串排序都在反复考字符串的比较、切片、拼接。把这些题连在一起刷你会发现字符串操作就是三件事切、拼、比。先看回文判断s input(请输入字符串: ) if s s[::-1]: print(是回文) else: print(不是回文)逻辑说明切片s[::-1]表示从末尾到开头以步长 -1 取字符串是判断回文最省事的写法。参数说明如果要求忽略大小写和空格可以加预处理s s.replace( , ).lower()。再看列表转字符串实例033的解法核心是joinchars [P, y, t, h, o, n] text .join(chars) print(text)逻辑说明join是字符串的方法参数必须是字符串列表不能有数字。如果列表里有数字需要先用map(str, chars)转换。实例018“复读机相加”则可以用abc * n或累加循环我推荐用乘号因为乘法的语义更清晰。刷这部分题时我一般会给自己加一个限制不许用拼接字符串强制用join。这样做能提前适应真实项目里处理大量字符串的场景因为在循环里会产生大量临时对象。3.4 面向对象与作用域类方法和实例变量的差别实例041到043连续考“类的方法与变量”“变量作用域”“作用域、类的的方法与变量”很多新手在这里翻车。先看一个最典型的例子class Demo: tag class var def __init__(self, name): self.name name def show(self): print(Demo.tag, self.name) a Demo(A) b Demo(B) a.tag changed print(Demo.tag, a.tag, b.tag)输出是class var changed class var。逻辑说明tag是类变量name是实例变量给a.tag赋值只会在 a 上创建同名实例属性不会改变类变量所以 b.tag 仍然是原来的类变量。实例041“类的方法与变量”、实例042“变量作用域”、实例043“作用域、类的方法与变量”基本都在考这一点。作用域的坑还在函数里。函数内部直接赋值一个变量Python 会把它当局部变量想修改全局变量要用global嵌套函数想修改外层函数变量要用nonlocal。很多新人卡在实例042就是因为在函数里写了x x 1解释器直接报 UnboundLocalError。解决办法是把变量放进可变容器或者在函数开头声明 global。步骤建议自己写一个类加一个类方法、一个实例方法、一个静态方法把三个方法的调用方式都打印出来。这个练习比单纯看答案有用得多。3.5 矩阵运算对角线之和与矩阵相加的下标控制矩阵类题目虽然只有两道但它的价值在二维列表下标控制。实例038求矩阵对角线之和实例044矩阵相加我先给一个标准实现def diagonal_sum(mat): total 0 n len(mat) for i in range(n): total mat[i][i] return total def anti_diagonal_sum(mat): total 0 n len(mat) for i in range(n): total mat[i][n - 1 - i] return total def mat_add(a, b): rows len(a) cols len(a[0]) return [[a[i][j] b[i][j] for j in range(cols)] for i in range(rows)]逻辑说明主对角线特征是行号等于列号副对角线特征是列号等于 n-1-行号。矩阵相加用两层循环外层控制行内层控制列返回新矩阵。参数说明这三个函数都假设输入是二维列表且方阵需要满足len(mat) len(mat[0])如果矩阵不是方阵diagonal_sum会越界所以要提前判断。实际刷题时我会先把矩阵写成一个三个元素的简单列表比如[[1,2],[3,4]]用纸笔标出每个元素的下标再去看代码。这一步做完实例038基本就通了。实例044 矩阵相加则提示你注意输入的两个矩阵维度必须相同否则要么报错、要么结果行列错乱。4. 从零跑通环境、批量执行与断言验证4.1 环境准备一个解释器加一个整洁目录刷这套题只需要 Python 3.8 以上不需要安装任何第三方库。目录结构可以这样python_100/ ├── answers/ │ ├── ex001.py │ ├── ex002.py │ └── ... ├── tests/ │ └── test_ex001.py └── run_all.py说明每个题目一个文件文件名用实例编号好处是跟目录一一对应。answers 放你的最终答案tests 放验证脚本run_all.py 做批量执行。这套结构对后面“换参数重跑”非常有帮助。为什么不直接用 Jupyter notebook因为 100 个题目更适合脚本化执行。Jupyter 适合探索但回溯不方便而且每个 cell 的输出会堆积在内存里。把答案拆成独立文件后你随时能单独重跑某一道题也能用脚本统一检查哪些题通过了、哪些题报错了。4.2 批量运行脚本把 100 道题变成一次命令如果你已经把所有答案写进 answers 目录可以用下面这个脚本批量执行import glob import subprocess import sys for filepath in sorted(glob.glob(answers/*.py)): print(, filepath, ) subprocess.run([sys.executable, filepath])逻辑说明glob.glob按文件名匹配到所有 py 文件sorted保证按编号顺序subprocess.run用当前解释器执行每个脚本。参数说明sys.executable就是当前 Python 环境的完整路径不会因为虚拟环境不同而找错解释器。这个脚本最大的问题是 input 类题目会卡住等待输入。常见做法是先把这类题改成从命令行参数读取或者在测试脚本里用 stdin 重定向。例如python answers/ex002.py 100000可以把 10 万这个测试值直接喂给程序。在 run_all.py 里想自动化就给 subprocess.run 加input或stdin参数。我一般会给每个脚本写一个带默认参数的 main 函数而不是直接裸露的 input这样批量执行才稳定。另外如果某个答案文件抛异常子进程崩溃不会影响主脚本继续执行所以你可以一次性看到哪些题崩了、哪些题正常。这个特性在刷完整套题时特别有用相当于拿到了一个自动化的“体检报告”。4.3 断言验证把输入输出题改造成可自动断言很多练习题是直接 print 结果不方便自动判断。我的做法是把核心逻辑改成函数再用 assert 验证。以实例001为例def combine(nums): res [] for i in nums: for j in nums: for k in nums: if i ! j and j ! k and i ! k: res.append((i, j, k)) return res assert len(combine([1, 2, 3, 4])) 24 assert (1, 2, 3) in combine([1, 2, 3, 4]) assert (1, 1, 2) not in combine([1, 2, 3, 4]) print(所有断言通过)逻辑说明把原来的三重循环包装成函数参数 nums 是数字列表返回所有满足条件的三元组。三个断言分别检查总数、有效组合、无效组合。参数说明你可以把[1, 2, 3, 4]换成[1, 2, 3]来测试不同规模断言仍然能复用。这套方法对递归题尤其重要。比如斐波那契你可以断言fib(0) 0、fib(10) 55避免肉眼检查输出。把题目从“打印型”改成“函数型”是一个很关键的过渡面试写算法题时用的也是这种模式。4.4 边界参数实验用几组临界值检验答案实例002的个税计算最容易错的边界值恰好是档位切换点。我一般会写一个循环测试多个利润值def calc_bonus(profit): bonus 0 limits [100000, 100000, 200000, 200000, 400000] rates [0.1, 0.075, 0.05, 0.03, 0.015, 0.01] for i in range(len(limits)): if profit limits[i]: bonus profit * rates[i] profit 0 break else: bonus limits[i] * rates[i] profit - limits[i] bonus profit * rates[-1] return bonus for p in [0, 100000, 100001, 200000, 400000, 600000, 1000000]: print(p, calc_bonus(p))逻辑说明calc_bonus返回奖金循环打印不同利润对应的结果。为什么要测这些值因为 100000 正好落在第一个档位的末尾100001 落在第二档开头这两个值最能检验条件判断是还是写错。参数说明limits 列表各个元素之和是 1000001000002000002000004000001000000刚好对应“高于100万元”的临界点。做完边界实验把结果和手工计算对比一遍基本就能确认这个题完全掌握。这套方法也可以套到闰年判断、素数判断上每次我都会额外测0和负数看看程序会不会给出不合理的负奖金。5. 避坑指南刷这套题最容易翻车的五个点5.1 实例003完全平方数上限推导不是万能的现象有人直接把参考答案里的while (n1)**2 - n*n 168得到的 n 当成最终上限然后for i in range((n1)**2)。当题目改成“加上200和180”或者换成更大的数时结果范围不够漏答案。原因这个 while 循环只是利用“n 的平方与 (n1) 的平方差 168”来估算最大间隙它给出的上限在本题刚好够用但不是数学证明。完全平方数的判断必须依赖平方根的小数为 0而不是依赖一个拍脑袋的上限。解决把上限设得大一些比如for i in range(10000)或者直接用while True配合退出条件更稳妥的做法是写一个辅助函数is_square(x)然后循环到 10000。我在重做这道题时会把 168 提取成变量方便下次改数。5.2 实例004闰年修改二月天数后第二次运行结果漂移现象在 IDLE 或 Jupyter 里重复运行同一个文件第一次输出正确第二次输出比预期多一天。原因代码里有一个列表DofM [0,31,28,31,30,31,30,31,31,30,31,30]遇到闰年执行DofM[2] 1。这个修改是永久性的只要进程不重启下一次再跑闰年就会在已经是 29 的基础上继续加变成 30。解决不要在全局列表上直接改。把二月的天数放到函数内部或者用副本调整month_days [0,31,28,31,30,31,30,31,31,30,31,30] if is_leap_year(year): month_days[2] 1或者每次都基于基础数据重建列表。这里我的教训是遇到“修改默认配置”的题先问一句这个修改是一次性的还是要被多次复用。5.3 递归无终止条件RecursionError 与重复计算现象递归求斐波那契时fib(100)直接报 RecursionError或者fib(35)运行很慢等半天没结果。原因一是递归深度超过 Python 默认限制约 1000 层二是没有记忆化的递归会重复计算大量子问题呈指数增长。解决先检查终止条件是否覆盖最小输入如果递归深度可能很大改成迭代或用functools.lru_cache缓存。实例026到028的递归题规模都不大但不要把递归当成万能钥匙像猴子偷桃这种可以反向递推的题用循环反而简单。刷到这类题我会强制自己先画递归树画出重复节点再决定要不要缓存。5.4 位运算按位取反为什么 ~5 输出 -6现象实例055按位取反有人预计~5是-5实际输出-6。原因Python 的整数是无限精度补码表示。按位取反会把每一位翻转包括符号位所以结果满足~x -(x1)。~5就是-(51) -6。解决不要硬记用bin(5)和bin(~5)对比看二进制。如果只想要无符号取反可以用5 ^ 0b111...或x ^ (2**n - 1)。刷位运算题时先把十进制转成二进制写出来再逐位计算比直接心算靠谱。5.5 time 模块格式化字符串大小写和平台差异现象%y和%Y分不清%m和%M混用导致输出月份变成分钟或者年份只有两位。原因time 模块的格式化里大小写有严格区分%y是两位年份%Y是四位年份%m是两位月份%M是分钟%S是秒%s是时间戳。不查文档直接写几乎必错。解决写代码前先跑一个最小的格式化实验比如time.strftime(%Y-%m-%d %H:%M:%S)确认输出再套进题目。实例091-096 连续五道 time 模块题本质就是让你记住常用格式。我每次用到都会打开文档查一眼不靠记忆硬写。6. 最后一步按目标过滤题号把题库变成自己的训练计划6.1 三套组合清单基础、面试、补弱根据目标选择不同题号组合目标题号组合说明快速过一遍基础001、002、006、008、012、013、036、038、097循环、数论、矩阵、文件都有面试前补算法011、020、021、024、026、027、028、038、044、061递归、递推、矩阵专项补弱字符串017、018、030、031、033、079文件097-099用知识点表定位怎么用从第一组开始每道题先写答案再运行最后把题目改一个参数重跑。比如实例001把 1-4 改成 0-9实例038把 3x3 矩阵改成 5x5改完还能跑对才算真正掌握。6.2 自测方法改参数、加限制、对比答案自己判断掌握程度的标准很简单能不能不看原题把代码重新写出来更严格一点试着加一个限制条件。比如实例004要求输出“第几天”你可以改成“离年末还有多少天”实例039有序列表插入元素你可以改成“插入后保持降序”。加限制之后原来的逻辑重排你才会去思考代码里的判断条件和数据结构。从那以后我每次推荐别人刷这套题都会强制走一遍“先写、再跑、再改参数”的流程。一百道题我不要求全刷完但每一道刷过的题都会留下一个带断言的脚本这样隔两周再跑一次马上知道有没有忘干净。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?