1. Python流程控制基础概念
流程控制是编程语言中最基础也最重要的概念之一,它决定了程序执行的顺序和逻辑分支。Python作为一门高级编程语言,提供了多种流程控制结构,让开发者能够灵活地控制代码的执行流程。
在Python中,流程控制主要分为三类:顺序结构、条件分支结构和循环结构。顺序结构是最简单的,代码按照从上到下的顺序依次执行;条件分支结构通过判断条件来决定执行哪部分代码;循环结构则用于重复执行某些代码块。
提示:Python使用缩进来表示代码块,这是与其他语言(如C、Java)使用大括号{}不同的地方。正确的缩进对于Python程序的正确执行至关重要。
1.1 为什么需要流程控制
想象你在写一个自动回复邮件的程序。如果没有流程控制,程序只能按照固定顺序执行相同的操作,无法根据邮件内容做出不同的回复。而有了流程控制,你可以:
- 判断邮件是否来自重要联系人(条件判断)
- 对不同类型的邮件采用不同的回复模板(多分支选择)
- 批量处理收件箱中的所有邮件(循环)
这就是流程控制在现实编程中的应用价值。它让程序具备了"智能",能够根据不同情况做出不同反应,而不仅仅是机械地执行固定步骤。
1.2 Python流程控制的特点
Python的流程控制有几个显著特点:
- 语法简洁:相比其他语言,Python的流程控制语法更加简洁明了
- 依赖缩进:使用缩进而非大括号来定义代码块
- 可读性强:关键字如if、else、for、while等直接表达了其功能
- 灵活性高:支持多种控制结构的嵌套和组合
这些特点使得Python的流程控制既强大又易于学习和使用,特别适合编程初学者入门。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 条件分支结构详解
条件分支是流程控制中最常用的结构之一,它允许程序根据不同的条件执行不同的代码块。Python提供了if、elif和else关键字来实现条件分支。
2.1 基本if语句
最简单的条件判断是单分支的if语句:
python复制if 条件表达式:
# 条件为真时执行的代码块
例如,判断一个数是否为正数:
python复制num = 10
if num > 0:
print("这是一个正数")
2.2 if-else语句
当需要处理条件不成立的情况时,可以使用if-else结构:
python复制if 条件表达式:
# 条件为真时执行的代码块
else:
# 条件为假时执行的代码块
继续上面的例子:
python复制num = -5
if num > 0:
print("这是一个正数")
else:
print("这不是一个正数")
2.3 多条件判断:if-elif-else
对于多个条件的情况,可以使用elif(else if的缩写):
python复制if 条件1:
# 条件1为真时执行
elif 条件2:
# 条件2为真时执行
else:
# 以上条件都不满足时执行
示例:成绩等级判断
python复制score = 85
if score >= 90:
print("优秀")
elif score >= 80:
print("良好")
elif score >= 60:
print("及格")
else:
print("不及格")
2.4 条件表达式的编写技巧
Python中的条件表达式非常灵活,可以包含各种比较和逻辑运算:
- 比较运算符:==, !=, >, <, >=, <=
- 逻辑运算符:and, or, not
- 成员运算符:in, not in
- 身份运算符:is, is not
示例:
python复制# 检查年龄在18到60之间且不是25岁
age = 30
if 18 <= age <= 60 and age != 25:
print("符合条件")
# 检查元素是否在列表中
fruits = ['apple', 'banana', 'orange']
if 'apple' in fruits:
print("苹果在水果列表中")
# 检查变量是否为None
value = None
if value is None:
print("值为空")
注意:在Python中,判断一个变量是否为None应该使用is None而不是== None,因为is比较的是对象标识,而==比较的是值。
2.5 条件表达式的短路特性
Python的条件表达式具有短路特性,这在编写复杂条件时非常有用:
python复制# 如果a为False,就不会计算b的条件
if a and b:
pass
# 如果a为True,就不会计算b的条件
if a or b:
pass
这个特性可以用来安全地处理可能为None的对象:
python复制# 安全的属性访问
if obj is not None and obj.property == value:
pass
3. 循环结构深入解析
循环结构用于重复执行某段代码,直到满足特定条件为止。Python提供了while和for两种循环结构。
3.1 while循环
while循环在条件为真时重复执行代码块:
python复制while 条件表达式:
# 循环体
示例:计算1到100的和
python复制total = 0
i = 1
while i <= 100:
total += i
i += 1
print(f"1到100的和是:{total}")
3.2 for循环
for循环用于遍历序列(如列表、元组、字符串等)或其他可迭代对象:
python复制for 变量 in 可迭代对象:
# 循环体
示例:遍历列表
python复制fruits = ['apple', 'banana', 'orange']
for fruit in fruits:
print(f"我喜欢吃{fruit}")
3.3 range()函数
在处理数字序列时,range()函数非常有用:
python复制# 打印0到4
for i in range(5):
print(i)
# 打印2到6
for i in range(2, 7):
print(i)
# 打印1到10,步长为2
for i in range(1, 11, 2):
print(i)
3.4 循环控制语句
Python提供了break、continue和pass来控制循环的执行:
- break:立即退出整个循环
- continue:跳过当前迭代,进入下一次循环
- pass:空操作,占位符
示例:
python复制# 查找第一个能被7整除的数
for num in range(1, 100):
if num % 7 == 0:
print(f"找到第一个能被7整除的数:{num}")
break
# 打印1到10的奇数
for num in range(1, 11):
if num % 2 == 0:
continue
print(num)
# pass示例(通常用于尚未实现的代码块)
for num in range(5):
pass # 待实现
3.5 循环的else子句
Python的循环可以有一个else子句,它在循环正常结束(没有被break中断)时执行:
python复制for num in range(2, 10):
for i in range(2, num):
if num % i == 0:
print(f"{num}等于{i}*{num//i}")
break
else:
print(f"{num}是一个质数")
这个特性在搜索算法中特别有用,可以区分找到和未找到的情况。
4. 高级流程控制技巧
掌握了基础的条件和循环结构后,我们来看一些Python中更高级的流程控制技巧。
4.1 嵌套循环
循环可以嵌套使用,用于处理多维数据结构或多重条件:
python复制# 打印九九乘法表
for i in range(1, 10):
for j in range(1, i+1):
print(f"{j}x{i}={i*j}", end="\t")
print() # 换行
4.2 列表推导式中的流程控制
列表推导式可以包含条件判断:
python复制# 生成1到10的偶数平方列表
even_squares = [x**2 for x in range(1, 11) if x % 2 == 0]
print(even_squares) # 输出: [4, 16, 36, 64, 100]
4.3 条件表达式(三元运算符)
Python提供了简洁的条件表达式语法:
python复制value = true_value if condition else false_value
示例:
python复制age = 20
status = "成年" if age >= 18 else "未成年"
print(status) # 输出: 成年
4.4 使用zip()并行迭代
当需要同时遍历多个序列时,可以使用zip()函数:
python复制names = ['Alice', 'Bob', 'Charlie']
scores = [85, 92, 78]
for name, score in zip(names, scores):
print(f"{name}的成绩是{score}")
4.5 使用enumerate()获取索引
在循环中同时需要索引和值时,使用enumerate():
python复制fruits = ['apple', 'banana', 'orange']
for index, fruit in enumerate(fruits):
print(f"索引{index}的水果是{fruit}")
5. 流程控制实战应用
现在让我们看几个实际应用场景,展示流程控制在解决实际问题中的威力。
5.1 用户登录验证
python复制max_attempts = 3
attempts = 0
stored_password = "secure123"
while attempts < max_attempts:
password = input("请输入密码:")
if password == stored_password:
print("登录成功!")
break
else:
attempts += 1
remaining = max_attempts - attempts
print(f"密码错误,还剩{remaining}次尝试机会")
else:
print("尝试次数过多,账户已锁定")
5.2 数据处理与过滤
python复制# 从数据中筛选出符合条件的信息
data = [
{"name": "Alice", "age": 25, "score": 85},
{"name": "Bob", "age": 30, "score": 92},
{"name": "Charlie", "age": 22, "score": 78},
{"name": "David", "age": 35, "score": 65}
]
# 筛选年龄在25-30岁之间且分数大于80的记录
filtered_data = []
for record in data:
if 25 <= record["age"] <= 30 and record["score"] > 80:
filtered_data.append(record)
print("筛选结果:")
for record in filtered_data:
print(f"{record['name']}, 年龄{record['age']}, 分数{record['score']}")
5.3 文件处理与模式匹配
python复制# 统计文本文件中各单词出现的频率
word_count = {}
with open("sample.txt", "r") as file:
for line in file:
words = line.strip().split()
for word in words:
word = word.lower() # 忽略大小写
if word in word_count:
word_count[word] += 1
else:
word_count[word] = 1
# 打印出现频率最高的5个单词
sorted_words = sorted(word_count.items(), key=lambda x: x[1], reverse=True)
print("最常见的5个单词:")
for word, count in sorted_words[:5]:
print(f"{word}: {count}次")
5.4 游戏逻辑实现
python复制# 简单的猜数字游戏
import random
target = random.randint(1, 100)
attempts = 0
max_attempts = 7
print("猜数字游戏(1-100),你有7次机会")
while attempts < max_attempts:
guess = int(input("请输入你的猜测:"))
attempts += 1
if guess < target:
print("猜小了!")
elif guess > target:
print("猜大了!")
else:
print(f"恭喜你!用了{attempts}次猜对了数字{target}")
break
remaining = max_attempts - attempts
if remaining > 0:
print(f"还剩{remaining}次机会")
else:
print(f"很遗憾,游戏结束。正确答案是{target}")
6. 常见问题与调试技巧
在实际使用Python流程控制时,经常会遇到一些问题。下面总结了一些常见问题及其解决方法。
6.1 缩进错误
Python对缩进非常敏感,常见的缩进错误包括:
- 混用空格和制表符
- 缩进层级不一致
- 缺少必要的缩进
建议:在编辑器中设置显示空白字符,并统一使用4个空格作为缩进。
6.2 无限循环
while循环容易因为条件永远为真而导致无限循环:
python复制# 错误示例:无限循环
i = 0
while i < 5:
print(i)
# 忘记增加i的值
解决方法:
- 确保循环条件最终会变为False
- 在开发阶段可以添加临时计数器,达到一定次数后强制退出
- 使用调试器或打印语句跟踪循环变量的变化
6.3 条件判断错误
常见的条件判断错误包括:
- 使用赋值运算符=而不是比较运算符==
- 复杂的逻辑表达式优先级错误
- 浮点数比较时的精度问题
示例:
python复制# 错误示例:使用=而不是==
if x = 5: # 语法错误
pass
# 浮点数比较的正确方式
a = 0.1 + 0.2
if abs(a - 0.3) < 1e-9: # 使用极小值作为容差
print("相等")
6.4 循环中的变量作用域
Python中没有块级作用域,循环中定义的变量在循环外仍然可以访问:
python复制for i in range(5):
pass
print(i) # 输出4,这可能不是预期的行为
如果需要在循环外部使用循环变量,建议在循环前显式初始化:
python复制result = None
for item in items:
if condition(item):
result = item
break
print(result)
6.5 性能优化技巧
当处理大数据集时,循环可能会成为性能瓶颈。一些优化建议:
- 尽量使用内置函数和库函数替代显式循环
- 使用列表推导式代替简单的for循环
- 避免在循环内部进行不必要的计算
- 考虑使用生成器表达式处理大数据集
示例:
python复制# 较慢的实现
result = []
for x in range(1000000):
result.append(x**2)
# 更快的实现
result = [x**2 for x in range(1000000)]
# 内存更友好的实现(生成器表达式)
result = (x**2 for x in range(1000000))
7. Pythonic的流程控制写法
Python社区有一些惯用的流程控制写法,被称为"Pythonic"的方式。掌握这些写法可以让你的代码更简洁、更高效。
7.1 使用any()和all()替代循环
python复制# 检查列表中是否有正数
numbers = [-1, 0, 2, -3]
if any(n > 0 for n in numbers):
print("存在正数")
# 检查是否所有数都是正数
if all(n > 0 for n in numbers):
print("都是正数")
else:
print("不全是正数")
7.2 使用字典替代多重if-elif
当有多个条件分支时,使用字典映射可能更清晰:
python复制# 传统方式
def handle_status(code):
if code == 200:
return "OK"
elif code == 404:
return "Not Found"
elif code == 500:
return "Server Error"
else:
return "Unknown Status"
# Pythonic方式
def handle_status(code):
status_map = {
200: "OK",
404: "Not Found",
500: "Server Error"
}
return status_map.get(code, "Unknown Status")
7.3 使用for-else结构
for-else结构在搜索场景中非常有用:
python复制# 检查列表中是否有偶数
numbers = [1, 3, 5, 7, 9]
for num in numbers:
if num % 2 == 0:
print("找到偶数")
break
else:
print("没有找到偶数")
7.4 使用itertools模块
itertools模块提供了许多高效的迭代器工具:
python复制from itertools import product, permutations, combinations
# 笛卡尔积
for x, y in product([1, 2], ['a', 'b']):
print(x, y)
# 排列
for p in permutations('ABC', 2):
print(p)
# 组合
for c in combinations('ABC', 2):
print(c)
7.5 使用上下文管理器处理资源
虽然不直接是流程控制,但with语句可以优雅地管理资源:
python复制# 传统方式
file = open('data.txt', 'r')
try:
data = file.read()
finally:
file.close()
# Pythonic方式
with open('data.txt', 'r') as file:
data = file.read()
# 文件会自动关闭
8. 流程控制的最佳实践
根据多年Python开发经验,我总结了一些流程控制的最佳实践,可以帮助你写出更健壮、更易维护的代码。
8.1 保持条件表达式简单
复杂的条件表达式难以理解和维护。建议:
- 将复杂条件分解为多个变量或函数
- 使用德摩根定律简化逻辑
- 避免过多的嵌套条件
示例:
python复制# 不易读的复杂条件
if (user.is_active and user.has_permission('edit') and
not user.is_banned and post.is_published):
pass
# 改进后的版本
can_edit = user.is_active and user.has_permission('edit')
is_allowed = can_edit and not user.is_banned
if is_allowed and post.is_published:
pass
8.2 限制嵌套层级
过深的嵌套会使代码难以理解。建议:
- 将深层嵌套的代码提取为函数
- 使用提前返回(early return)减少嵌套
- 考虑使用不同的算法或数据结构
示例:
python复制# 深层嵌套的代码
def process_data(data):
if data is not None:
if len(data) > 0:
for item in data:
if item.is_valid():
# 处理逻辑
pass
# 改进后的版本
def process_data(data):
if data is None or len(data) == 0:
return
for item in data:
if not item.is_valid():
continue
# 处理逻辑
8.3 合理使用循环控制语句
break、continue和return的使用建议:
- 在循环开始处使用continue处理特殊情况
- 使用break提前终止不必要的迭代
- 在函数中,使用return替代break来完全退出
示例:
python复制# 查找第一个满足条件的元素
def find_first(predicate, items):
for item in items:
if predicate(item):
return item
return None
8.4 编写清晰的循环
循环应该具有清晰的意图:
- 使用有意义的循环变量名
- 在循环开始前注释说明循环的目的
- 保持循环体简短,复杂逻辑提取为函数
示例:
python复制# 计算学生平均分,忽略缺考(分数为None)
def calculate_average(scores):
total = 0
count = 0
for score in scores:
if score is not None:
total += score
count += 1
return total / count if count > 0 else 0
8.5 测试边界条件
确保流程控制正确处理边界情况:
- 空列表或空输入
- 最小/最大值
- 刚好满足/不满足条件的值
- None或其他特殊值
示例测试用例:
python复制# 测试边界条件
assert calculate_average([]) == 0
assert calculate_average([None, None]) == 0
assert calculate_average([100]) == 100
assert calculate_average([60, 70, None, 80]) == 70
9. 流程控制在不同Python版本中的变化
Python的流程控制语法在不同版本中保持相对稳定,但也有一些值得注意的变化和增强。
9.1 Python 3.8中的海象运算符
Python 3.8引入了赋值表达式(海象运算符:=),可以在表达式中赋值:
python复制# 传统方式
line = input()
while line != "quit":
print(f"你输入了: {line}")
line = input()
# 使用海象运算符
while (line := input()) != "quit":
print(f"你输入了: {line}")
9.2 Python 3.10中的结构模式匹配
Python 3.10引入了match-case语句,提供了更强大的模式匹配功能:
python复制def handle_command(command):
match command.split():
case ["quit"]:
print("退出程序")
case ["load", filename]:
print(f"加载文件: {filename}")
case ["save", filename]:
print(f"保存到文件: {filename}")
case _:
print("未知命令")
9.3 字典合并与更新操作符
Python 3.9引入了|和|=用于字典合并,简化了字典操作:
python复制# 合并字典
dict1 = {"a": 1, "b": 2}
dict2 = {"b": 3, "c": 4}
merged = dict1 | dict2 # {"a": 1, "b": 3, "c": 4}
# 就地更新
dict1 |= dict2 # dict1变为{"a": 1, "b": 3, "c": 4}
9.4 类型注解的增强
新版本Python对类型注解的支持不断增强,可以在流程控制中提供更好的类型提示:
python复制from typing import Optional
def greet(name: Optional[str] = None) -> str:
if name is None:
return "Hello, anonymous!"
else:
return f"Hello, {name}!"
10. 流程控制在实际项目中的应用案例
让我们看几个实际项目中流程控制的典型应用,这些案例来自真实的Python项目。
10.1 Web框架中的路由处理
在Web框架如Flask或Django中,流程控制用于路由和视图处理:
python复制# Flask路由示例
from flask import Flask, request
app = Flask(__name__)
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
username = request.form['username']
password = request.form['password']
if validate_credentials(username, password):
return redirect('/dashboard')
else:
return render_template('login.html', error="Invalid credentials")
else:
return render_template('login.html')
10.2 数据处理管道
在数据分析和机器学习项目中,流程控制用于构建数据处理管道:
python复制def process_data(raw_data):
results = []
for record in raw_data:
try:
# 数据清洗
cleaned = clean_record(record)
# 特征提取
features = extract_features(cleaned)
# 验证数据
if validate_features(features):
results.append(features)
except DataError as e:
log_error(e)
continue
return results
10.3 命令行工具开发
在开发CLI工具时,流程控制用于解析参数和执行命令:
python复制import argparse
def main():
parser = argparse.ArgumentParser()
parser.add_argument('command', choices=['start', 'stop', 'status'])
parser.add_argument('--verbose', action='store_true')
args = parser.parse_args()
if args.command == 'start':
start_service(verbose=args.verbose)
elif args.command == 'stop':
stop_service(verbose=args.verbose)
elif args.command == 'status':
show_status(verbose=args.verbose)
def start_service(verbose=False):
if verbose:
print("启动服务...")
# 启动逻辑
10.4 游戏开发中的主循环
游戏开发中,主游戏循环是流程控制的典型应用:
python复制def game_loop():
player = Player()
enemies = [Enemy() for _ in range(5)]
running = True
while running:
# 处理输入
for event in pygame.event.get():
if event.type == QUIT:
running = False
elif event.type == KEYDOWN:
handle_input(event.key, player)
# 更新游戏状态
player.update()
for enemy in enemies:
enemy.update(player)
if check_collision(player, enemy):
handle_collision(player, enemy)
# 渲染
render(player, enemies)
# 检查游戏结束条件
if player.health <= 0:
running = False
show_game_over()
10.5 网络编程中的事件循环
在网络编程中,流程控制用于处理连接和请求:
python复制import socket
def handle_client(conn, addr):
print(f"连接来自: {addr}")
while True:
data = conn.recv(1024)
if not data:
break
response = process_request(data)
conn.sendall(response)
conn.close()
def start_server(host, port):
with socket.socket() as s:
s.bind((host, port))
s.listen()
print(f"服务器启动,监听 {host}:{port}")
while True:
conn, addr = s.accept()
handle_client(conn, addr)
11. 流程控制的性能考量
虽然Python的流程控制语法简洁,但在性能敏感的场景中,仍然需要注意一些优化技巧。
11.1 循环性能优化
- 避免在循环内部进行不必要的计算
- 将不变的计算移到循环外部
- 使用局部变量替代全局变量访问
- 考虑使用内置函数替代显式循环
示例:
python复制# 较慢的实现
results = []
for item in large_list:
results.append(expensive_operation(item) * global_multiplier)
# 更快的实现
local_multiplier = global_multiplier # 避免在循环中访问全局变量
results = [expensive_operation(item) * local_multiplier
for item in large_list] # 使用列表推导式
11.2 条件判断的性能
条件表达式的顺序会影响性能:
python复制# 将最可能为True的条件放在前面
if likely_condition or unlikely_condition:
pass
# 将计算简单的条件放在前面
if simple_to_compute and complex_to_compute:
pass
11.3 使用生成器处理大数据集
对于大数据集,使用生成器可以节省内存:
python复制# 一次性读取整个文件到内存
with open('large_file.txt') as f:
lines = f.readlines() # 可能消耗大量内存
for line in lines:
process(line)
# 使用生成器逐行处理
with open('large_file.txt') as f:
for line in f: # 逐行迭代,内存友好
process(line)
11.4 利用短路求值特性
Python的条件表达式具有短路求值特性,可以利用这一点优化代码:
python复制# 如果obj可能为None,先检查None
if obj is not None and obj.property == value:
pass
# 如果expensive_check()计算成本高,放在后面
if simple_check() and expensive_check():
pass
11.5 选择合适的数据结构
不同的数据结构对流程控制的性能影响很大:
python复制# 列表的成员检查是O(n)
if item in my_list: # 慢
pass
# 集合的成员检查是O(1)
if item in my_set: # 快
pass
12. 流程控制的调试与测试
编写健壮的流程控制代码需要良好的调试和测试实践。下面介绍一些有用的技巧。
12.1 使用断言检查前置条件
python复制def divide(a, b):
assert b != 0, "除数不能为零"
return a / b
12.2 添加调试输出
在开发阶段,可以添加临时打印语句帮助调试:
python复制for i, item in enumerate(data):
print(f"处理第{i}项: {item}") # 调试输出
result = process(item)
if result is None:
print(f"警告: 第{i}项处理失败") # 调试输出
continue
12.3 使用pdb调试器
Python内置的pdb调试器可以单步执行代码:
python复制import pdb
def complex_function(x):
pdb.set_trace() # 设置断点
y = x * 2
if y > 10:
return y
else:
return y + 10
12.4 编写单元测试
使用unittest或pytest等框架测试流程控制逻辑:
python复制import unittest
def is_even(n):
return n % 2 == 0
class TestEvenCheck(unittest.TestCase):
def test_positive(self):
self.assertTrue(is_even(2))
self.assertFalse(is_even(1))
def test_negative(self):
self.assertTrue(is_even(-2))
self.assertFalse(is_even(-1))
def test_zero(self):
self.assertTrue(is_even(0))
if __name__ == '__main__':
unittest.main()
12.5 使用覆盖率工具
使用coverage.py等工具检查测试覆盖率,确保所有分支都被测试:
bash复制# 安装
pip install coverage
# 运行测试并检查覆盖率
coverage run -m unittest test_module.py
coverage report -m
13. 流程控制的扩展应用
除了基础的条件和循环,Python的流程控制还可以与其他语言特性结合,实现更强大的功能。
13.1 使用装饰器控制函数流程
装饰器可以修改函数的行为,实现如权限检查、日志记录等功能:
python复制def log_time(func):
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(f"{func.__name__}执行时间: {end-start:.2f}秒")
return result
return wrapper
@log_time
def expensive_operation():
time.sleep(1)
return "结果"
expensive_operation() # 会自动打印执行时间
13.2 使用上下文管理器控制资源
上下文管理器(with语句)可以确保资源被正确释放:
python复制class DatabaseConnection:
def __enter__(self):
self.conn = connect_to_database()
return self.conn
def __exit__(self, exc_type, exc_val, exc_tb):
self.conn.close()
with DatabaseConnection() as conn:
conn.execute_query("SELECT * FROM users")
# 连接会自动关闭
13.3 使用生成器控制执行流程
生成器函数可以暂停和恢复执行,用于实现协程和流式处理:
python复制def data_processor():
data = yield # 接收数据
while True:
try:
processed = process_data(data)
data = yield processed # 返回处理结果并接收新数据
except GeneratorExit:
cleanup()
break
processor = data_processor()
next(processor) # 启动生成器
result = processor.send("第一批数据") # 发送数据并获取结果
13.4 使用协程实现异步流程
asyncio库提供了基于协程的异步流程控制:
python复制import asyncio
async def fetch_data(url):
print(f"开始获取 {url}")
await asyncio.sleep(2) # 模拟IO操作
print(f"完成获取 {url}")
return f"{url}的数据"
async def main():
task1 = asyncio.create_task(fetch_data("url1"))
task2 = asyncio.create_task(fetch_data("url2"))
data1 = await task1
data2 = await task2
print(f"获取到数据: {data1}, {data2}")
asyncio.run(main())
13.5 使用异常控制错误流程
异常处理是流程控制的重要组成部分:
python复制def process_file(filename):
try:
with open(filename) as f:
data = f.read()
except FileNotFoundError:
print(f"文件 {filename} 不存在")
return None
except PermissionError:
print(f"没有权限读取文件 {filename}")
return None
except Exception as e:
print(f"处理文件时发生未知错误: {e}")
return None
else:
return process_data(data)
finally:
print(f"文件处理完成: {filename}")
14. 流程控制的常见设计模式
在软件开发中,有一些常用的设计模式大量依赖流程控制。了解这些模式可以帮助你更好地组织代码。
14.1 策略模式
使用不同的策略处理相同的问题:
python复制def strategy_add(a, b):
return a + b
def strategy_multiply(a, b):
return a * b
def execute_strategy(strategy, a, b):
return strategy(a, b)
result = execute_strategy(strategy_add, 3, 4) # 7
result = execute_strategy(strategy_multiply, 3, 4) # 12
14.2 状态模式
根据对象的状态改变行为:
python复制class State:
def handle(self):
pass
class StateA(State):
def handle(self):
print("处理状态A")
return StateB()
class StateB(State):
def handle(self):
print("处理状态B")
return StateA()
class Context:
def __init__(self):
self.state = StateA()
def request(self):
self.state = self.state.handle()
context = Context()
context.request() # 处理状态A
context.request() # 处理状态B
14.3 模板方法模式
定义算法的骨架,允许子类重写特定步骤:
python复制from abc import ABC, abstractmethod
class Template(ABC):
def template_method(self):
self.step1()
self.step2()
self.step3()
def step1(self):
print("默认步骤1")
@abstractmethod
def step2(self):
pass
def step3(self):
print("默认步骤3")
class Concrete(Template):
def step2(self):
print("具体实现步骤2")
concrete = Concrete()
concrete.template_method()
14.4 责任链模式
将请求沿着处理链传递,直到有对象处理它:
python复制class Handler:
def __init__(self, successor=None):
self.successor = successor
def handle(self, request):
if self.can_handle(request):
return self.process(request)
elif self.successor:
return self.successor.handle(request)
else:
return None
def can_handle(self, request):
pass
def process(self, request):
pass
class HandlerA(Handler):
def can_handle(self, request):
return 0 <= request < 10
def process(self, request):
return f"HandlerA处理了{request}"
class HandlerB(Handler):
def can_handle(self, request):
return 10 <= request < 20
def process(self, request):
return f"HandlerB处理了{request}"
chain = HandlerA(HandlerB())
print(chain.handle(5)) # HandlerA处理了5
print(chain.handle(15)) # HandlerB
