Part 1:Python语言核心 - Control Flow 控制流

Python Control Flow 控制流

控制流的本质:决定代码在什么条件下执行、执行多少次、是否中断、如何优雅表达逻辑。

if / elif / else

基本结构和执行规则

python 复制代码
if condition1:
    ...
elif condition2:
    ...
else:
    ...
# 从上至下,条件成立则执行。

条件表达式(Truth Value Testing)

Python 中,if 后面不要求是 bool。

python 复制代码
if obj:
    ...

判断规则:

  • 若对象定义了 __bool__() ,使用其返回值。
  • 否则若定义了 __len__()len(obj) > 0True
  • 否则 True

常见的 False 值:

  • None
  • False
  • 0
  • ""
  • []{}set()
python 复制代码
if data:			# 判断是否为空
if result is None:	# 判断是否为 None (推荐)

工程级原则

  • 判断"有没有",if x:
  • 判断"是不是 None",is None:

短路逻辑(and / or)

执行规则

python 复制代码
a and b
# a 为 False 返回 a
# a 为 True 返回 b

a or b
# a 为 True 返回 a
# a 为 False 返回 b

返回的不是 True 或 False ,而是原始对象。

常见用法

设置默认值

python 复制代码
name = user_input or "anonymous"

防御式编程

python 复制代码
obj and obj.method()

优点:

  • 少写 if
  • 表达力强
  • 性能好
python 复制代码
x = a or b	# 当 a = 0 / "" / [] 时,不可能是我们想要的

if-else 表达式(三元表达式)

python 复制代码
x = a if condition else b

for / while

1. for 循环的本质

python 复制代码
for x in iterable:
    ...

for 不是计数循环,而是:

遍历实现了 迭代器协议 的对象

底层等价逻辑(简化):

python 复制代码
it = iter(iterable)
while True:
    try:
        x = next(it)
    except StopIteration:
        break

📌 这解释了:

  • 为什么 for 能遍历 list / dict / file / generator
  • 为什么 for 不需要索引

2. range() 的本质

python 复制代码
range(start, stop, step)

特点:

  • 返回的是 range 对象
  • 惰性计算
  • 不存储所有整数
python 复制代码
range(1_000_000)	# 几乎不占内存

📌 工程意义:

  • for + range 是高效组合
  • 比自己维护计数器安全

3. while 循环

python 复制代码
while condition:
    ...

适合场景:

  • 循环次数不确定
  • 状态驱动逻辑

⚠️ 风险:

  • 忘记修改 condition → 死循环

📌 实践建议:

  • while 一定要有 清晰的退出路径

4. for / while + else

python 复制代码
for x in data:
    if x == target:
         break
else:
    print("not found")

语义:

循环正常结束(没有 break)才执行 else

❌ 不是"兜底"

❌ 不是"最后一次执行"

常见用途:

  • 查找
  • 校验
  • 验证完整性

📌 这是 Python 非常独特、但非常优雅的控制流设计。

break / continue / pass

1. break

  • 立即终止最近一层循环
  • 跳过 else
python 复制代码
for x in data:
    if x < 0:
        break

2. continue

  • 跳过当前迭代
  • 进入下一轮
python 复制代码
for x in data:
    if x < 0:
        continue
    process(x)

📌 使用 continue 的核心目标:

减少嵌套,提高可读性


3. pass

复制代码
if condition:
    pass

本质:

  • 语法占位符
  • 什么都不做

常见用途:

  • 代码结构占位
  • 空类 / 空函数
  • 尚未实现的分支

⚠️ 陷阱:

  • 不要用 pass 掩盖未处理逻辑

match-case (Python 3.10+)

match-case ≠ switch

它是 结构化模式匹配

1. 常量匹配

python 复制代码
match x:
    case 1:
        ...
    case 2 | 3 | 5:		# 3 或 4 或 5
        ...
    case _:
        ...

_

  • 通配符
  • 不绑定变量
  • 永远匹配

2. 解构匹配

python 复制代码
match point:
    case (0, 0):
        ...
    case (x, y):
        ...
match data:
    case {"id": id_, "name": name}:
        ...

📌 本质:

  • 结构 + 模式
  • 不只是值相等
python 复制代码
point = (3, 4)

match point:
    case (0, 0):
        print("origin")
    case (x, 0):
        print(f"x-axis, x={x}")
    case (0, y):
        print(f"y-axis, y={y}")
    case (x, y):		# 走这个分支
        print(f"point ({x}, {y})")

长度敏感 list 解构

python 复制代码
data = [1, 2, 3]

match data:
    case [a, b]:
        print("two elements")
    case [a, b, c]:
        print(a, b, c)
    case _:
        print("other")
*rest 变长结构匹配
python 复制代码
data = [1, 2, 3, 4, 5]

match data:
    case [first, *middle, last]:
        print(first, middle, last)

输出:

python 复制代码
1 [2, 3, 4] 5
dict 解构匹配
python 复制代码
data = {
    "id": 1001,
    "name": "Alice",
    "age": 18
}

match data:
    case {"id": id_, "name": name}:
        print(id_, name)

📌 关键认知(非常重要):

dict 解构是"子集匹配"

  • 不要求 key 完全一致
  • 只关心写出来的 key
  • 其余 key 会被忽略

⚠️ 容易踩坑的点

复制代码
case {"id": 1001, "name": name}:

这里:

  • 1001常量匹配
  • name变量绑定
解构 + 守卫 (Guard)
python 复制代码
user = {"id": 3, "role": "admin"}

match user:
    case {"id": id_, "role": "admin"} if id_ > 0:
        print("valid admin")
    case _:
        print("other")

📌 流程是:

1️⃣ 结构匹配

2️⃣ 变量绑定

3️⃣ 执行 if 守卫判断

不是反过来。

类型解构(类实例匹配)
python 复制代码
class Point:
    __match_args__ = ("x", "y")

    def __init__(self, x, y):
        self.x = x
        self.y = y

p = Point(1, 2)

match p:
    case Point(0, 0):
        print("origin")
    case Point(x, y):
        print(x, y)

📌 这是 match-case 最容易被低估的一点

它能把「对象 + 属性访问 + if 判断」

变成 结构化语义


match-case vs if-elif 的思维差异(核心)

老 Python 思维

复制代码
if isinstance(x, tuple) and len(x) == 2:
    a, b = x
    ...

match-case 思维

复制代码
match x:
    case (a, b):
        ...

📌 不是"判断 + 解包"

📌 而是:"我期望你的结构是这样"

综合例子
python 复制代码
def handle(msg):
    match msg:
        case {"type": "ping"}:
            return "pong"

        case {"type": "move", "pos": (x, y)}:
            return f"move to {x}, {y}"

        case {"type": "chat", "text": text} if text:
            return f"say: {text}"

        case _:
            return "unknown"

"结构化的协议解析"

这在:

  • Web API
  • 消息队列
  • 游戏逻辑
  • 状态机
    里非常强。

推导式 (Conprehensions)

四种推导式

列表推导式
python 复制代码
[x * 2 for x in range(5)]

等价于

python 复制代码
result = []
for x in range(5):
    result.append(x * 2)

特点:

  • 立即计算
  • 返回 list
  • 占用完整内存
字典推导式
python 复制代码
{k: v * 2 for k, v in data.items()}

本质:

python 复制代码
result = {}
for k, v in data.items():
    result[k] = v * 2

常见高级用途:

python 复制代码
{v: k for k, v in data.items()}
集合推导式
python 复制代码
{x % 3 for x in range(10)}

自动去重。

生成器推导式
python 复制代码
(x * 2 for x in range(5))

区别:

  • 不立即计算
  • 返回 generator
  • 惰性求值
  • 节省内存

常见工程写法:

python 复制代码
sum(x * 2 for x in range(10_000_000)

如果用 list,会炸内存。

条件推导式

过滤条件
python 复制代码
[x for x in range(10) if x % 2 == 0]

等价于:

python 复制代码
for x in range(10):
    if x % 2 == 0:
        result.append(x)
表达式中的 if-else
python 复制代码
[x if x % 2 == 0 else -1 for x in range(10)]

等价于:

python 复制代码
for x in range(10):
    result.append(x if x % 2 == 0 else -1)

[表达式 if 条件 else 表达式 for ...][表达式 for ... if 条件] 含义完全不同。

多层 for 的执行顺序

python 复制代码
[(i, j) for i in range(2) for j in range(3)]

执行顺序:

python 复制代码
for i in range(2):
    for j in range(3):
        result.append((i,j))

记忆口诀:

从左到右读

执行顺序是嵌套展开

带条件的复杂例子

python 复制代码
[(i, j) for i in range(3) if i != 1 for j in range(3)]

等价于:

python 复制代码
for i in range(3):
    if i != 1:
        for j in range(3):
            result.append((i, j))

推导式的作用域

Python 2 的坑
python 复制代码
x = 10
lst = [x for x in range(5)]
print(x)	# Python2 会变成 4

因为变量泄露。

Python 3 的行为
python 复制代码
x = 10
lst = [x for x in range(5)]
print(x)	# 10

推导式有自己的局部作用域。

本质:

Python 3 会在内部创建一个隐式函数作用域。



隐藏陷阱

闭包 + 推导式:

python 复制代码
funcs = [(lambda: i) for i in range(3)]

for f in funcs:
    print(f())

输出:

tex 复制代码
2
2
2

原因:

  • lambda 捕获的是变量 i
  • 而不是当时的值
  • 循环结束时 i = 2

正确写法:

python 复制代码
funcs = [(lambda i=i: i) for i in range(3)]

这是经典 late binding 问题。

lambda 匿名函数,在需要函数的地方快速写一个临时小函数

python 复制代码
lambda 参数: 表达式
  • 只能写一个表达式
  • 不能写多条语句
  • 自动返回表达式结果(隐式 return)


性能&底层原理

为什么列表推导式比普通循环快?

因为:

  • append 在 C 层完成
  • 减少 Python 字节码跳转
  • 局部变量访问更快

CPython 会专门优化推导式

生成器 VS 列表推导式
类型 是否立即计算 内存 适合
列表 小数据
生成器 大数据流

高级工程技巧

与 any / all 结合
python 复制代码
any(x < 0 for x in nums)

优点:

  • 不生成列表
  • 遇到 True 立即停止
  • 隐式 break
python 复制代码
any(iterable)
  • 参数必须是可迭代对象
  • 返回布尔值
python 复制代码
all(iterable)	# 只有全部为 True 才返回 True
all([True, True, False])	# 返回 False
all(x > 0 for x in nums)

常见用法:如数据合法性校验。

python 复制代码
if not all(isinstance(x, int) for x in nums):
    raise TypeError
与 next 结合
python 复制代码
next((x for x in nums if x > 5), None)

优雅查找第一个符合条件的元素。等价于:

python 复制代码
for x in nums:
    if x > 5:
        return x
return None

next() 从迭代器中获取"下一个元素"。

语法:

python 复制代码
next(iterator)

python 复制代码
next(iterator, default_value)

没有默认值 next(it) 当没有元素时,StopIteration 异常。有默认值 next(it, None) 就不会报错。


函数 作用 何时停止
any 有一个 True 即 True 遇 True
all 全 True 才 True 遇 False
next 取第一个元素 取到即停

本质上,它们都是在做控制循环的提前终止,而不用写 for, break, return 。

性能优势

错误写法:

python 复制代码
if True in [x < 0 for x in nums]:

这会:

  • 生成完整列表
  • 占用额外内存

正确写法:

复制代码
any(x < 0 for x in nums)
  • 不生成列表
  • 惰性计算
  • 短路退出

嵌套推导式的可读性边界

python 复制代码
[(i, j) for i in range(3) for j in range(3) if (i + j) % 2 == 0]

可读。但是如果超过两层嵌套:

  • 改成普通循环
  • 或拆成函数

工程优先级:

可读性 > 短代码


可迭代对象 & 迭代器

列表是可迭代对象 iterable,但不是迭代器 iterator。

  • iterable 可以被 for 遍历
  • iterator 可以被 next() 不断取下一个值

什么是可迭代对象?

是否实现了 __iter__() 方法。

python 复制代码
nums = [1, 2, 3]
print(hasattr(nums, "__iter__()"))	# True

什么是迭代器?

必须同时有:

  • __iter__()
  • __next__()
python 复制代码
it = iter([1, 2, 3])
print(hasattr(it, "__next__"))	# True

for 循环底层原理:

python 复制代码
for x in nums:
    print(x)

底层其实是:

python 复制代码
it = iter(nums)
while True:
    try:
        x = next(it)
        print(x)
    except StopIteration:
        break
相关推荐
非凡ghost1 小时前
Smart Launcher安卓版(安卓桌面启动器)
android·windows·学习·音视频·软件需求
阿_旭1 小时前
【旋转框】基于YOLO26深度学习的无人机视角车辆检测系统【python源码+Pyqt5界面+数据集+训练代码】
python·深度学习·无人机·车辆检测
m0_716667071 小时前
C++中的访问者模式高级应用
开发语言·c++·算法
大鹏说大话1 小时前
构建高并发缓存系统:架构设计、Redis策略与灾难防御
开发语言
Oueii1 小时前
C++中的访问者模式变体
开发语言·c++·算法
2401_838683372 小时前
单元测试在C++项目中的实践
开发语言·c++·算法
guygg882 小时前
基于Kaimal谱的风速时间序列生成MATLAB程序
开发语言·matlab
Pyeako2 小时前
opencv计算机视觉--PaddleOCR的实时多语言文本检测与识别
人工智能·python·opencv·计算机视觉·ocr·paddleocr
jianghao20252 小时前
realesrgan-gui跨平台使用指南:Win/Mac/Linux全支持
linux·windows·mac·跨平台软件·realesrgan-gui