大家好,我是程序员柏风,AI 最全的 Vibecoding 学习地图 http://coderoadmap.cn 作者。
语法与缩进
这一课你将能做到
- 写一个包含注释、多级缩进、多种语句的完整脚本并一次跑通
- 看到缩进类报错(IndentationError / TabError)时,30 秒内定位并修复
- 说清 Python 为什么用缩进代替大括号,以及「冒号 + 4 空格」这套规则的完整口径
为什么要学
Java 用 {} 圈代码块,分号结尾;Python 把这两样都省了,改用缩进表示「谁属于谁」。好处是代码天生整齐、不会出现垃圾格式;代价是缩进不是风格问题,是语法问题——多打一个空格,程序直接报错。这一课不解决缩进,后面每一课都会被它绊住。
人话:缩进就像 Word 里的层级列表——一级标题下的内容都缩进一格,表示「这些属于这个标题」。Python 里 if、for、def 后面跟个冒号,下一行开始缩进的代码都「属于」它,缩进结束,代码块就结束。
先建立图像
同一段逻辑,Java 与 Python 对照:
// Java:花括号定边界,缩进只是好看
if (score >= 60) {
System.out.println("及格");
} else {
System.out.println("不及格");
}
# Python:缩进就是边界本身
if score >= 60:
print("及格")
else:
print("不及格")
结构图:
if score >= 60: ← 冒号:声明「下面是我的代码块」
print("及格") ← 4 空格缩进:属于 if
print("继续加油") ← 同样 4 空格:和上面同属 if
print("程序结束") ← 顶格:不属于 if,无论如何都执行
跟着做
步骤 1:写第一个带缩进的脚本
新建 indent_demo.py:
score = 85
if score >= 90:
print("优秀")
print("继续保持") # 这行与上一行同属 if
elif score >= 60:
print("及格")
else:
print("不及格")
print("程序执行完毕") # 顶格,不属于任何块
运行:
python indent_demo.py
输出:
及格
程序执行完毕
三个观察点:elif 是 else if 的缩写;每个分支都以冒号结尾;print("程序执行完毕") 顶格,所以不属于任何分支,必然执行。
步骤 2:亲手制造一次 IndentationError
把上面文件里 print("及格") 前面多加 2 个空格(变成 6 个空格),保存再跑:
python indent_demo.py
输出:
File "indent_demo.py", line 8
print("及格")
IndentationError: unexpected indent
这就是「缩进不一致」的报错。改回 4 个空格,恢复正常。记住这个报错的样子,以后见到它,第一反应就是「查缩进」。
步骤 3:缩进层级可以嵌套
缩进里还能再缩进,每层都是 4 空格:
students = ["阿黄", "阿绿", "阿蓝"]
for name in students:
if name == "阿绿":
print(f"{name}:请假") # 两层缩进:for 里嵌 if
else:
print(f"{name}:出勤")
输出:
阿黄:出勤
阿绿:请假
阿蓝:出勤
步骤 4:注释的三种用法
# 这是单行注释,井号后面的内容解释器全部忽略
print("可见") # 行尾注释:解释这一行在干嘛
# 多行注释的惯例做法:连续多个单行
# 第一步:读取配置
# 第二步:连接数据库
# 第三步:开始处理
"""
三个引号包裹的叫文档字符串(docstring),
严格说它是一个字符串值而不是注释,
但常被放在文件/函数开头当说明用。
"""
print("注释演示结束")
输出:
可见
注释演示结束
步骤 5:一条语句的续行写法
太长的行可以用括号隐式换行(推荐),或反斜杠显式续行:
total = (1 + 2 + 3
+ 4 + 5) # 括号内可以随便换行
print(total)
text = "这是一段很长很长" \
"的字符串拼接" # 反斜杠续行,少用
print(text)
输出:
15
这是一段很长很长的字符串拼接
步骤 6:分号与一行多语句
Python 允许但不推荐:
a = 1; b = 2; print(a + b) # 语法合法,风格差评
输出:
3
团队规范和官方 PEP 8 都要求:一行一条语句,不写分号。
讲清楚要点
- 缩进是语法,不是审美:Java 里缩进乱了只是难看,Python 里缩进错了直接不运行。同一个代码块必须缩进完全一致。
- 标准是 4 个空格:PEP 8 规定 4 空格,禁止 Tab 与空格混用。编辑器里把 Tab 键设置为「插入 4 空格」(VS Code 右下角点「Tab Size」可改),一劳永逸。
- 冒号开启代码块:
if/elif/else/for/while/def/class/try等语句末尾都是冒号,看到冒号,下一行必缩进。 - 代码块靠「缩进结束」退出:没有
},也没有end。缩进回退到上一层级,块就结束了。这解释了为什么步骤 1 里最后一行必然执行。 - 空行不影响缩进逻辑:代码块中间的空行会被忽略,可以放心用空行分组;但注释行如果带缩进,保持和所在块一致更易读。
- 报错信息会指路:
IndentationError: unexpected indent= 多缩进了;expected an indented block= 冒号后面没缩进;TabError= Tab 和空格混用。三个报错对应三种典型错法。
你可能会懵的地方
-
为什么不学 Java 用大括号,省得折腾? 设计取舍:强制统一缩进后,任何人写出的 Python 格式都基本一致,读别人的代码成本骤降。大括号时代「缩进骗人」(括号对齐 A、缩进看着像 B)的 bug 在 Python 里天然不存在。
-
空格数错一个就会报错,太苛刻了吧? 只要求「同一块内一致」。顶层语句顶格,块内统一 4 空格,嵌套每层加 4 空格——就这三条规则,没有别的。
-
从网上复制的代码缩进乱了怎么办? VS Code 里全选(Ctrl+A)→ Ctrl+Shift+P → 输入 "Convert Indentation to Spaces" → 选 4。一次转换,全局修复。
-
单行 if 能不换行直接写吗? 能:
if score >= 60: print("及格")。合法但只适合极短语句,初学阶段老老实实换行缩进,养成肌肉记忆。 -
docstring 和注释到底啥区别? 注释(
#)解释器直接丢弃;docstring 是真实的字符串对象,会被存在函数/类的__doc__属性里,help()函数和很多工具会读它。日常「给自己看」用#,「给使用者看」用 docstring。
错法对照
| 错法 | 问题 | 正解 |
|---|---|---|
| 冒号后直接写语句不换行(长代码) | 可读性差、易漏缩进 | 冒号后换行 + 4 空格缩进 |
| Tab 和空格混用 | TabError,且不同编辑器显示不同 | 编辑器设置 Tab=4 空格,只用空格 |
| 复制网页代码后直接跑 | 缩进深度混杂,IndentationError | Convert Indentation to Spaces 统一后跑 |
| 用分号把多条语句挤一行 | 违反 PEP 8,难调试断点 | 一行一条语句 |
| 注释行顶格写进深层代码块中间 | 不报错但阅读错乱 | 注释与所在代码块同缩进 |
| 以为加空行能「跳出」代码块 | 空行不改变块结构 | 回退缩进才是结束代码块 |
卡点急救
- IndentationError: unexpected indent:报错行比同块其他行缩进多。数空格,统一为 4。
- IndentationError: expected an indented block:冒号后面忘了写内容或没缩进。冒号下一行必须缩进;暂时没逻辑先写
pass占位。 - TabError: inconsistent use of tabs:Tab 与空格混用。VS Code 右下角把缩进转成空格。
- 看着缩进明明对,还是报错:文件里混了不可见字符。用 VS Code 「显示空白字符」(设置搜索 render whitespace)逐行检查;或整段删掉手敲。
- 改了缩进报错更多了:可能只改了块内一行,同块其他行不一致。整块一起选中,统一 Tab/Shift+Tab 调整。
面试常问
-
Python 为什么用缩进而非大括号?你的看法? 官方立场是提升可读性与一致性:缩进是所有工程师阅读时真正依赖的信息,强制它统一后代码风格天然收敛。代价是对空白字符敏感、复制粘贴易错、工具链必须配合。答出「取舍」二字比站队更重要。
-
PEP 8 是什么?说几条你遵守的规范。 Python 官方风格指南。可答:缩进 4 空格、一行一条语句、运算符两侧留空格、函数间空两行、变量名 snake_case、常量全大写。追问 PEP 全称是 Python Enhancement Proposal(Python 增强提案)。
-
pass语句的作用? 空操作占位符。Python 语法上要求冒号后必须有缩进块,当结构先搭好、逻辑后补时用pass占位,保证代码能运行。 -
TabError 和 IndentationError 什么关系? TabError 是 IndentationError 的子类,专指 Tab 与空格混用导致的歧义缩进。都继承自 SyntaxError,在解析阶段就报。
自测三问
if/def/for这些语句开启代码块的统一标志是什么?代码块靠什么结束?IndentationError: expected an indented block的三种常见成因?- PEP 8 对缩进、一行语句数、命名风格分别怎么规定?
小结一句话
Python 用「冒号开块、缩进定界、4 空格标准」取代大括号——缩进即语法,管好编辑器的空格设置,IndentationError 就再也追不上你。
延伸
- PEP 8 —— 官方风格指南
- The Python Tutorial — Using the Interpreter
- 下一课预告:类型与变量——Python 变量不声明类型,但「一切皆对象」;int、float、bool、None 和 type() 一次讲清。