1. 从“Python小屋”前10题说起:为什么这批题值得认真做
董付国老师的Python小屋,在学Python的圈子里几乎是绕不开的名字。我最初接触这套“Python小屋编程题1-10”的时候,其实没太当回事,觉得前10道题能有多难?不就是print、input、if、for轮着来一遍嘛。但真正坐下来把每一道题都写完、跑通、再回头优化一遍之后,我才意识到,这个系列的前10题根本不是“给你练手用的简单题”,而是一套经过精心设计的入门逻辑链。
这套题的定位非常清楚:帮你把Python最基础、最核心的语法点,通过“解决问题”的方式刻进脑子里。它不像很多刷题网站那样,上来就给你一个复杂的算法题,而是从最朴素的输入输出开始,一步步过渡到条件判断、循环、字符串处理、列表操作,最后落到一个小型综合应用上。你可以把它理解成学车时的“科目二”——项目不多,但每一个动作都是在为后面的上路打基础。
适合谁来刷这套题?第一类是刚装好Python、连print都还没写利索的纯新手,这10题能帮你把“写代码”这件事从“看懂了”变成“真会了”;第二类是学过语法但总觉得“做题没思路”的人,这套题的解题路径会告诉你,拿到一个题目以后应该先想什么、再想什么;第三类是像我这种带学生入门的老师或者学长,拿这套题当作业模板,再配上自己的讲解,带新人的效率会高很多。
接下来说说我自己的一个观点:很多人学Python喜欢追新、追热,什么数据分析、爬虫、量化交易、人工智能,一上来就装numpy、装pandas、跑模型。但你让他写一个“输入三个数,输出最大值”,他能卡半小时。这就是典型的地基没打牢。董老师的这10道题,恰恰是帮你把地基夯实的那一铲子土。
2. 动手前的准备:环境、运行方式与解题顺序
刷题之前先把工具准备好,这一步看似简单,但我在带人过程中发现,至少有三分之一的新手会卡在环境上,而不是卡在题目本身。
2.1 环境准备:装Python和VS Code,别在这一步偷懒
Python的安装其实没什么难度,去官网下载对应你操作系统的安装包,安装时一定要勾选“Add Python to PATH”,这一步非常重要。很多同学装完以后在终端敲python提示“不是内部或外部命令”,基本都是因为这个选项没勾。装完以后打开命令行,输入python --version能正常输出版本号,就算过了环境这一关。
编辑器我建议用VS Code。理由很简单:免费、轻量、插件生态成熟。装完VS Code以后,在扩展商店里搜“Python”,安装微软官方那个插件就行。它会自动帮你做语法高亮、代码补全和缩进检查。关于缩进,这是Python和新手之间最容易爆发冲突的地方,因为Python用缩进表示代码块,混用Tab和空格、或者缩进量不一致,都会直接报IndentationError。
提示:我建议你在VS Code里把“Editor: Insert Spaces”设置为True,缩进宽度设为4空格,并且养成“只用Tab键、让编辑器自动转成空格”的习惯,能省掉后面大量排版问题。
2.2 虚拟环境与运行方式:不吃亏的小习惯
刷前10题的时候,用系统自带的Python解释器直接跑完全够用,没必要非建一个虚拟环境。但你如果打算后面学爬虫、数据分析、Web开发,那我建议从今天开始就养成一个习惯:每个学习项目建一个独立的虚拟环境。
在项目文件夹里打开终端,执行:
python -m venv venv然后激活它。Windows下激活命令是:
venv\Scripts\activatemacOS和Linux下是:
source venv/bin/activate看到命令行前面出现(venv)标记,就说明虚拟环境生效了。这样做的好处是,你在这个项目里pip install的包不会污染全局环境,也不会出现“这个项目需要numpy 1.x,另一个项目需要numpy 2.x,结果互相打架”的情况。
运行方式上,我推荐直接在VS Code里右键文件选择“在终端中运行Python文件”,或者用右上角的三角形按钮。前10题不需要复杂的调试工具,看到输出结果就够用了。等后面题目变长,需要一步步看代码执行状态的时候,再用断点调试。
2.3 解题顺序与时间分配:别迷信“按顺序刷完”,要懂得拆解
题目编号是1到10,但我不建议你机械地一天刷一道。我的建议是:按知识点分组刷,而不是按题号刷。第1题到第3题大概率是输入输出、变量和表达式,这几道题一天内集中做完,能帮你把“程序如何接收数据、如何处理数据、如何输出结果”这条链路打通。第4到第6题大概率涉及if条件判断,第7到第9题涉及循环和列表,第10题往往是综合运用。
每一道题,我建议按照“读题拆需求 → 独立写代码 → 对照测试用例 → 回看优化”的顺序来做。特别是最后一步“回看优化”,很多人忽略它,但这恰恰是提升最大的一步。你第一遍写出来的代码能跑就行,但你要回头问自己三个问题:能不能少写几行?能不能更通用?别人会怎么写?带着这三个问题去改代码,一道题顶三道题。
3. 前10题里最常考的几类题,我拆给你看
下面我挑选几类在1-10题里最常出现的题型,每一类我都会讲清楚:考查什么知识点、拿到题怎么想、代码怎么写、有哪些坑。我不去猜测题目原文长什么样,但这类题型的解题思路是通用的,你手头不管拿到的是什么变体,思路都能直接套。
3.1 输入输出与类型转换:一切题目都用得到的基本功
这类题最典型的场景是:“输入两个数,求和”“输入一个三位数,输出它的个位、十位、百位”。看起来简单,但它是前10题里第一个真正的分水岭。
很多新手第一次在这类题上栽跟头,问题出在一个非常基础的机制上:input()返回的永远是字符串。你输入123,拿到的是一个包含字符'1'、'2'、'3'的字符串,而不是数字123。这时候你直接用变量去做加法,结果不是求和,而是把两个字符串拼在一起。比如输入5和7,你得到的是“57”,而不是12。
所以第一步必须做类型转换。写法是:
a = input("请输入第一个数:") b = input("请输入第二个数:") a = int(a) b = int(b) print(a + b)简洁一点可以写成:
a = int(input("请输入第一个数:")) b = int(input("请输入第二个数:")) print(a + b)第二种写法把int()嵌套在input()外面,一步到位。这里要说清楚,int()只能把“看起来像整数”的字符串转成整数,你输入“3.14”,int()会直接报错,因为3.14不是整数。如果你要处理小数,要用float()。
处理三位数拆分的题目,核心是整除和取余的配合使用。拿到135这个数,要求输出个位5、十位3、百位1,最简单的思路是:
num = int(input("请输入一个三位数:")) a = num // 100 # 百位 b = num // 10 % 10 # 十位 c = num % 10 # 个位 print(a, b, c)这里有一个容易混的点:整除//是向下取整,135 // 100得到1;135 // 10得到13,再取余10得到3;135 % 10直接得到5。这个组合方式,后面做加密、做数据拆分还会反复用到,必须记牢。
3.2 条件判断:让程序学会做决定
第二类高频题型是条件判断类的:“判断一个数是正数、负数还是零”“判断闰年”“输入成绩,输出等级”。这类题考查的核心是if-elif-else结构,以及条件的先后顺序。
我见过很多新手写成绩等级判断的时候,条件顺序安排得很随意。比如:
score = int(input("请输入成绩:")) if score >= 60: print("及格") elif score >= 85: print("优秀")这段代码逻辑上有问题。因为Python的if-elif是自上而下匹配的,只要score >= 60成立,它就执行“及格”分支,后面的elif根本没机会跑。所以成绩85分以上的人,在这里也只能得到“及格”的结果。
正确写法要让条件从苛刻到宽松:
score = int(input("请输入成绩:")) if score >= 85: print("优秀") elif score >= 60: print("及格") else: print("不及格")这个顺序原则叫做“先收窄,后放宽”。排序的时候,条件越严格、范围越小的分支越要放前面。这个思维不仅在条件判断里重要,后面写异常处理、写递归出口,全都要用同一个逻辑。
判断闰年的题则是一个典型的“复合条件”训练。闰年的规则是:能被4整除但不能被100整除,或者能被400整除。翻译成代码:
year = int(input("请输入年份:")) if (year % 4 == 0 and year % 100 != 0) or year % 400 == 0: print(year, "是闰年") else: print(year, "不是闰年")注意那个and和or的优先级。Python里and的优先级高于or,所以这里加不加括号其实结果都一样,但加上括号能让读代码的人一眼看清你的逻辑分组。写代码不只是写给机器跑的,也是写给人看的,让看的人不费劲,本身就是一种能力。
3.3 循环与累加:计算机最擅长的事
循环类是前10题里绝对的大头。“求1到100的和”“求n的阶乘”“输出九九乘法表”这些题,都是拿for和while练手。这类题的核心价值在于让你理解“重复”这件事怎么写。
先看累加问题。求1到100的和,最朴素的写法:
total = 0 for i in range(1, 101): total += i print(total)这里面藏着Python新手必须明白的range机制:range(1, 101)生成的是1到100的整数序列,结束值101是不包含的。很多同学写成range(1, 100),结果发现结果比正确答案少100,就是这个左闭右开的边界没记牢。
total这个变量在循环开始之前初始化成0,这叫做“累加器”。累加器必须在循环外初始化,如果放在循环里,每次循环都会把它重置成0,最后得到的就不是累加结果,而是最后一个值。这个问题我在学生的作业里看到过无数次,几乎每届都有人犯。
求阶乘的题稍微变一下思路,乘法累加的初始值不能是0,因为任何数乘以0都是0,结果恒等于0。正确初始值应该是1:
n = int(input("请输入n:")) result = 1 for i in range(1, n + 1): result *= i print(result)这个“初始值到底取0还是取1”的判断标准是:你做的运算的“不变元素”是什么。加法的不变元素是0,乘法的不变元素是1。这个道理想通了,后面很多问题都自然通了。
九九乘法表这类输出嵌套结构的题目,考查的核心是嵌套循环。外层循环控制行,内层循环控制列:
for i in range(1, 10): for j in range(1, i + 1): print(f"{j}*{i}={i * j}", end="\t") print()这里有个细节:print()默认会在末尾加一个换行,但乘法表里每一行的内容必须连续输出,所以要用end="\t"把换行替换成制表符,等内层循环全部跑完以后,再单独调用一个空的print()来换行。乍一看这个print()放在哪好像无所谓,但实际上一行内容结束后必须由它来“收尾”,这是新手最容易卡住的地方。
3.4 字符串与列表:从单点操作到批量处理
进入前10题的后半段,字符串和列表就该登场了。典型的题目有:“输入一串字符,统计数字、字母个数”“反转字符串”“求列表中最大值和平均值”。
统计字符个数这类题,考查的是字符串遍历。字符串是个序列,可以像列表一样用for循环逐个字符去取:
s = input("请输入字符串:") digit_count = 0 letter_count = 0 for ch in s: if ch.isdigit(): digit_count += 1 elif ch.isalpha(): letter_count += 1 print("数字个数:", digit_count) print("字母个数:", letter_count)isdigit()和isalpha()是字符串的内置方法,分别用来判断字符是不是数字、是不是字母。这里有个坑需要注意:isdigit()对汉字数字也判断为True,比如'三'就不是数字;但'3'是True。如果你只要判断阿拉伯数字,条件写成'0' <= ch <= '9'更窄更明确。具体用哪种,取决于题目要求。
反转字符串的题,有直接的切片写法:
s = input("请输入字符串:") print(s[::-1])这个写法里的[::-1]是Python切片的一个特殊用法,表示从头到尾步长为-1,效果就是从后往前取值。这道题的背后其实是在考查你对切片语法的理解,slice的完整格式是[start:stop:step],step为负数时表示反向取值。
列表题则更进一层次。比如输入5个数存进列表,求最大值。你不应该上来就调max()函数,虽然Python确实内置了它,但前10题阶段你最好自己用循环实现一遍,否则训练不到“遍历+比较”的核心思维:
nums = [] for i in range(5): num = float(input("请输入第%d个数:" % (i + 1))) nums.append(num) max_num = nums[0] for num in nums: if num > max_num: max_num = num print("最大值是:", max_num)注意求最大值时,max_num的初始值取的是列表第一个元素,而不是0。因为如果列表里全是负数,初始值0会直接成为最大值,结果就错了。这个小细节,恰好就是“会用max函数”和“理解max原理”的分界线。
3.5 前10题常客:字符串与列表的组合应用
这类题目通常把字符串和列表结合起来,比如“输入一串用空格分隔的数字,算出它们的平均值”。这种题你就发现,前面东西全串起来了:
s = input("请输入数字,用空格分隔:") parts = s.split() nums = [] for part in parts: nums.append(float(part)) average = sum(nums) / len(nums) print("平均值:", average)split()是字符串方法,作用是按指定的分隔符把字符串切成一个列表。默认不传参数时,它会按空白字符切分,连续多个空格也能正确处理。这一小段代码虽然不长,但里面涵盖了字符串拆分、类型转换、列表append、sum求和、len求长度,五个点全部融合在一起,前10题的训练目标到这里基本就达成闭环了。
4. 初学刷题最容易踩的坑,一次给你讲清楚
这一章我要把带新人时反复遇到的高频报错和逻辑问题整理成一份避坑手册,每一条都是我实际看别人踩过、或者干脆是自己当年踩过的。
4.1 高频报错与排查对照表
| 报错信息 | 出现场景 | 原因 | 排查与修复 |
|---|---|---|---|
| NameError: name 'xxx' is not defined | 使用了未定义的变量或函数 | 变量名拼错,或者忘记赋值 | 检查变量名是否一致,是否在前面已赋值 |
| IndentationError: unexpected indent | 代码缩进不规范 | 混用了Tab和空格,或缩进量不一致 | 在VS Code里统一设置缩进为4空格,全部改用Tab键输入 |
| TypeError: can only concatenate str | 直接用+连接字符串和数字 | 没有做类型转换 | 用str()把数字转成字符串,或者用格式化输出 |
| ValueError: invalid literal for int() | input()结果是字符串,直接转int但内容不是整数 | 输入的内容含小数点、空格或中文 | 用float()转换,或者先清理字符串再转换 |
| IndexError: list index out of range | 访问列表不存在的下标 | 下标越界 | 打印列表长度,确认下标范围在0到len-1之间 |
| AttributeError: 'int' object has no attribute | 对整数调用了字符串方法 | 类型混淆,把整数当字符串用 | 检查变量类型,确认为字符串后再调用字符串方法 |
这个表里,第二行的缩进错误是最容易在“复制粘贴”时引入的。很多人喜欢从网页上复制代码片段到自己的文件里,结果网页里的Tab空格混排,一运行直接一片红。我的建议是:刷题阶段不要人肉复制网络代码,自己动手敲,哪怕敲得慢,敲一遍的肌肉记忆远比你想象中重要。如果确实要粘贴,粘完以后在VS Code里全选文件,然后执行“Ctrl+Shift+P”调出命令面板,输入“Convert Indentation to Spaces”,可以快速统一缩进。
4.2 排查思路:不要盯着报错看,要顺着逻辑找
遇到报错的时候,新手最容易犯的毛病是盯着最后的错误信息发呆。正确做法是:先看报错信息里的文件名和行号。比如:
File "main.py", line 7, in <module> print(x) NameError: name 'x' is not definedline 7告诉我问题出在第7行,print(x)这一行在找x这个变量却找不到。这时候我应该往上回溯,看看x是不是在第4行赋值时拼写成小写x、在第7行误写成大写X了。报错信息本身不一定会直接告诉你答案,但它会把问题精准定位到某一行,顺着这一行的上下文去排查,效率要高得多。
除了语法报错,还有一类更难排查的“逻辑错误”,就是程序能跑、结果不对。这时候我的办法是“分段打印验证”。比如求平均值总是不对,我就把split之后的列表print出来看看,再把转换后的数字列表print出来看看,每一步都确认数据状态是否符合预期。通常两处print下去,问题就暴露了:要么是某个数被解析成字符串,要么是累加器被重置了。这种调试手法,熟练以后自然就内化成一种直觉。
注意:程序输出正常并不代表逻辑正确。边界条件是逻辑题的照妖镜。做完题以后,一定要拿几个特殊值去测:0、负数、最大值、最小值、空字符串、只有一个元素。比如判断闰年的题,你拿1900去测,它是整百年但能被100整除,不是闰年;拿2000去测,能被400整除,是闰年。两个边界值一跑,代码对不对立刻见分晓。
5. 做完前10题之后,怎么把这套功力用起来
前面讲的全是“怎么把题做出来”,这一章我想聊点更重要的:做完这10道题以后,拿这些能力去干什么。
先纠正一个常见误区:“我刷完编程题1-10,是不是就算入门了?”答案是:算,也不算。算,是因为你已经能独立写出“输入→处理→输出”的完整程序,具备了最核心的编程思维雏形;不算,是因为你目前掌握的语法还停留在基础层,文件读写、函数返回值、异常处理、面向对象这些真正能让你“干活”的内容,还在后面等着你。
我的建议是,刷完前10题以后立刻做三件延伸的事。
第一件事,把前10题里你写过的最长的代码,改造一遍。目标是把所有处理逻辑拆成函数。比如平均数那道题,拆成“读入数据”函数和“计算平均值”函数。拆完以后你会发现,代码虽然变长了,但结构反而清晰了,哪里出问题一眼就能看到维护点。这个习惯,是应对后面几千行代码的唯一靠谱策略。
第二件事,找一本带实例的入门书或者一套经典100题,按知识点分类继续横向刷。比如“python经典100编程题”里有很多和这些题难度相当的题目,刷的时候刻意跳过你已经完全掌握的知识点,专攻薄弱项。刷题最忌讳的是待在舒适区里重复劳动,你觉得“我都会”的那些题,其实早就不该再花时间了。
第三件事,结合你的实际场景,做一个“无用但有趣”的小工具。学了条件判断和循环,你可以写一个猜数字游戏;学了字符串处理,你可以写一个统计自己聊天记录里高频词的小脚本;学了列表,你可以做一个简单的待办事项管理。这些东西虽然小,但它让你从“做题的人”变成“用工具解决问题的人”,这两个角色之间有一道坎,趁热打铁迈过去,后续学什么都快。
我自己带过不少学生,一个非常明显的规律是:愿意在基础题上反复打磨的人,后面学函数、学文件、学爬虫、学数据分析,上手速度普遍比急着赶进度的人快。原因很简单,基础题练的不是语法,而是把问题拆解成步骤、把步骤翻译成代码的那种“翻译感”。语法可以靠查文档补,翻译感只能靠练习攒。
写到最后说一句实在话。董付国老师把这道题编成“小屋”系列,名字起得特别好。编程这件事,本来就是在自己搭的小屋里,一盏灯,一台电脑,一行一行地把想法变成现实。前10道题就是那个小屋的地基,地基打牢了,后面你想往上盖几层楼都随你。