Python 基础语法 - 缩进与代码块
在所有编程语言中,都存在一个抽象概念:
代码块(block)= 一组在"同一语义上下文"中执行的语句集合
代码块通常用于:
- 条件控制(if / else)
- 循环(for / while)
- 函数体
- 类体
- 异常处理(try / except / finally)
- 上下文管理(with)
不同语言表示代码块的方法
| 语言 | 表示方式 |
|---|---|
| C / C++ / Java | { ... } |
| JavaScript | { ... } |
| Go | { ... } |
| Python | 缩进(Indentation) |
👉 关键区别 :
Python 的缩进 不是风格 ,而是 语法的一部分。
Python 缩进不仅只是为了好看,更是语法的需要。Python 使用缩进的层级代替了 {}。
缩进的基本规则
规则一
冒号 : 表示"下面会有一个新代码块"
出现位置包括:
python
if condition:
for x in iterable:
while condition:
def func():
class MyClass:
try:
except Exception:
with open(...) as f:
👉 冒号不是装饰,而是语法信号
规则二
同一个代码块,缩进必须一致
python
if x > 0:
print(x)
print("ok")
❌ 错误示例:
python
if x > 0:
print(x)
print("ok") # 多了一个层级
⚠️ Tab vs Space(这是个大坑)
if x > 0:
<TAB>print(x)
<SPACE><SPACE><SPACE><SPACE>print("ok")
这在视觉上可能对齐,但在解释器看来:
❌ 两种不同的缩进
结果:
TabError: inconsistent use of tabs and spaces in indentation
📌 结论:
- Python 官方规范(PEP 8):4 个空格
- 永远不要混用 Tab 和 Space
- 编辑器里:开启"显示不可见字符",VS code 设置搜索:render Whitespace ---> boundary
缩进如何影响程序的执行逻辑
缩进 = 控制流的边界
python
if x > 0:
print("A")
print("B")
print("C")
执行顺序:
- x > 0 → A → B → C
- x ≤ 0 → C
python
if x > 0:
print("A")
print("B")
print("C")
执行顺序:
- x > 0 → A → B → C
- x ≤ 0 → B → C
📌 结论:
缩进直接决定"哪些语句受控制结构影响"
嵌套缩进 = 嵌套语义
python
if x > 0:
if x > 10:
print("big positive")
print("positive")
等价逻辑:
IF
└── IF
└── print
└── print
从解释器角度看:缩进处理方式
词法分析阶段处理缩进
python 编译流程简化版:
源代码
→ 词法分析(Tokenize)
→ 语法分析(AST)
→ 字节码
→ 虚拟机执行
在 词法分析阶段,Python 会生成三种特殊 token:
INDENTDEDENTNEWLINE
python
if x > 0:
print(x)
print("ok")
print("end")
Token 流概念化:
scss
IF
NAME(x)
>
NUMBER(0)
:
NEWLINE
INDENT
NAME(print)
(...)
NEWLINE
NAME(print)
(...)
NEWLINE
DEDENT
NAME(print)
(...)
📌 关键理解:
Python 是靠
INDENT / DEDENTtoken 来判断代码块边界的不是靠视觉对齐
为什么 Python 强制使用缩进
这是设计哲学问题。
Python 的核心理念之一(PEP 20)
Explicit is better than implicit
Readability counts
在 C/Java 中:
if (x > 0)
do_a();
do_b(); // 实际不在 if 内(易错)
Python 通过缩进:
- 消灭"看起来像一块,实际上不是"的代码
- 强迫你写出逻辑与视觉一致的程序
📌 Python 把"人类的阅读结构"变成"机器的语法结构"
常见错误 & 反直觉点
以为空行会结束代码块:
python
if x > 0:
print(x)
print("still inside")
👉 空行不影响缩进结构
对其else错位:
python
if x > 0:
print(x)
if x > 10:
print("big")
else:
print("small") # else 绑定的是内层 if
📌 else 永远绑定最近的、同级缩进的 if
try/except缩进错位:
python
try:
risky()
except ValueError:
handle()
cleanup() # 仍在 except 内
缩进与作用域的关系
缩进 ≠ 作用域
python
if True:
x = 10
print(x) # 可以访问
原因:
- Python 没有块级作用域
- if / for / while 不创建新作用域
- 只有:函数、类、模块
📌 缩进用于控制执行,不一定用于隔离变量
这是 Python 与 C/Java 的重大差异之一。
工程级最佳实践
- 永远使用 4 个空格
- 编辑器开启:
- 显示缩进线
- 禁止 Tab
- 缩进层级 ≤ 3(超过就要重构)
- 看到复杂嵌套:
- 提前
return - 拆函数
- 提前
- 用缩进表达"逻辑主线",不是堆代码