当前位置: 首页 > article >正文

Python入门教程丨2.3 流程控制、算法效率分析及优化

流程控制是用于控制程序执行顺序的机制,它决定了程序中的语句按照何种顺序被执行。

本节课将详细讲解 Python 流程控制的三大核心结构:顺序、条件和循环,并配备一些小案例。


1. 顺序结构:从头到尾依次执行

顺序结构是程序中最基础的控制方式,代码会按照书写顺序从上到下逐行执行,没有任何跳转或判断。

例如我们用输出字符串的方式模拟一个日常活动,依次完成:

print("早上起床")
print("刷牙洗脸")
print("开始学习 Python 流程控制")
print("总结笔记并练习")

程序输出:

早上起床
刷牙洗脸
开始学习 Python 流程控制
总结笔记并练习

亦或是一个简易的计算器,给出两数进行加减乘除:

num1 = 10
num2 = 5

add = num1 + num2
subtract = num1 - num2
multiply = num1 * num2
divide = num1 / num2

print(f"加法结果:{add}")
print(f"减法结果:{subtract}")
print(f"乘法结果:{multiply}")
print(f"除法结果:{divide}")

2. 条件结构:让代码学会“拐弯”

条件结构通过判断条件是否成立,决定执行哪段代码,从流程图上看就是一个岔路口,不同的条件走不同的路线。

在 Python 中,条件控制结构主要有 if-elsematch-case 两种形式,它们各自适用于不同场景。

2.1 if-else

我们首先来看较常用的if-else

语法格式:

if 条件:
    执行语句1
elif 条件:
    执行语句2
else:
    其他情况

例如我们通过输入分数,判断学生的成绩:

score = int(input("请输入分数:"))
if score >= 90:
    print("优秀!")
elif 70 <= score < 90:
    print("良好!")
elif 60 <= score < 70:
    print("及格!")
else:
    print("不及格,请努力!")

又或者是输入三条边,判断是否能构成三角形,并判定类型:

a = int(input("请输入第一条边:"))
b = int(input("请输入第二条边:"))
c = int(input("请输入第三条边:"))

if a + b > c and a + c > b and b + c > a:
    if a == b == c:
        print("这是一个等边三角形!")
    elif a == b or b == c or a == c:
        print("这是一个等腰三角形!")
    else:
        print("这是一个普通三角形!")
else:
    print("无法构成三角形。")
2.2 match-case

match-case 是 类似于其他语言中的 switch-case。它适用于明确的值匹配或简单的模式匹配场景。

语法格式:

match 表达式:
case 情况1:
    执行语句1
case 情况2:
    执行语句2
case _:
    默认执行语句

适用范围:

  • 条件是固定值或简单的匹配模式,如具体的数值。
  • 多个条件分支数量较多且独立。

例如我们按照星期安排活动:

day = input("请输入星期几(如星期天):")

match day:
case "星期一":
    print("今天是周一,安排组会!")
case "星期二":
    print("今天是周二,团队讨论!")
case "星期五":
    print("今天是周五,准备周报!")
case _:
    print("今天没有特别安排。")

3. 循环结构

循环结构可以让代码反复执行某些操作。Python 提供了两种主要循环:for 循环和 while 循环。


3.1 for 循环

for 循环是迭代式循环,用于遍历序列(如列表、元组、字符串等)中的每个元素,或者循环特定次数。

语法:

for 变量 in 可迭代对象:
    执行语句

适用范围:

  • 确定循环次数。
  • 需要遍历序列中的每个元素。

例如计算列表元素的和

numbers = [1, 2, 3, 4, 5]
total = 0
for num in numbers:
    total += num
print(f"列表的总和是:{total}")

嵌套循环指在一个循环内再包含另一个循环,适用于需要多层次迭代的场景。

经典案例:打印九九乘法表

for i in range(1, 10):  # 外层控制行
    for j in range(1, i + 1):  # 内层控制列
        print(f"{j}×{i}={i * j}", end="\t")  # 使用制表符对齐
    print()  # 每行结束后换行

输出结果:

1 × 1 = 1    
1 × 2 = 2    2 × 2 = 4    
1 × 3 = 3    2 × 3 = 6    3 × 3 = 9    
1 × 4 = 4    2 × 4 = 8    3 × 4 = 12    4 × 4 = 16    
1 × 5 = 5    2 × 5 = 10    3 × 5 = 15    4 × 5 = 20    5 × 5 = 25    
1 × 6 = 6    2 × 6 = 12    3 × 6 = 18    4 × 6 = 24    5 × 6 = 30    6 × 6 = 36    
1 × 7 = 7    2 × 7 = 14    3 × 7 = 21    4 × 7 = 28    5 × 7 = 35    6 × 7 = 42    7 × 7 = 49    
1 × 8 = 8    2 × 8 = 16    3 × 8 = 24    4 × 8 = 32    5 × 8 = 40    6 × 8 = 48    7 × 8 = 56    8 × 8 = 64    
1 × 9 = 9    2 × 9 = 18    3 × 9 = 27    4 × 9 = 36    5 × 9 = 45    6 × 9 = 54    7 × 9 = 63    8 × 9 = 72    9 × 9 = 81    

3.2 while 循环:灵活性更强的循环

while 循环是条件式循环,反复执行代码块,直到条件为 False

语法:

while 条件:
    执行语句

适用范围:

  • 循环次数不确定,但有明确的终止条件。
  • 循环依赖某种动态计算的条件。

例子:猜数字游戏,并不能确保第几次猜对,就需要用 while 条件判断。

import random

secret_number = random.randint(1, 10)
attempts = 3

while attempts > 0:
    guess = int(input("猜猜我是几(1-10):"))
    if guess == secret_number:
        print("恭喜你,猜对了!")
        break
    elif guess < secret_number:
        print("小了!")
    else:
        print("大了!")
    attempts -= 1

if attempts == 0:
    print(f"很遗憾,正确答案是:{secret_number}")

3.3 break 和 continue循环控制语句
  • break:提前结束循环。
  • continue:跳过本次循环,继续下一次。

例如需要过滤奇数

for i in range(10):
    if i % 2 == 0:
        continue
    print(f"奇数:{i}")

4.时间复杂度与算法效率

在引入循环的概念后,我们就需要开始注重算法效率,循环在程序中往往会被反复执行,是性能瓶颈的主要来源之一。

而顺序结构是一次性执行的,运行时间是固定的,与输入规模无关。例如:

x = 5
y = x + 1
print(y)

无论输入规模多大,这些操作只执行一次,它们的时间复杂度是 O(1),无需深入分析。

循环执行的次数直接影响程序的运行时间,如果循环次数随着输入规模显著增加,会导致程序运行缓慢,甚至无法处理较大的输入。因此,分析循环的算法效率至关重要。


4.1 什么是时间复杂度?

时间复杂度是描述算法执行时间与输入规模之间关系的指标,用大O符号表示。例如:

  • O(1) 表示操作的执行时间不随问题规模变化。
  • O(n) 表示执行时间与问题规模成正比。
  • O(n^2) 表示执行时间与问题规模成平方次比。

一般来说,一次循环的时间复杂度为 O(n),嵌套循环的时间复杂度为 O(n^2),当然具体问题需要具体分析,也有可能是 O(nlog2n)。但总体来说,嵌套循环会大大增加时间复杂度,编写程序时注意用其他方式替换来优化。

时间复杂度让我们预测程序在不同输入规模下的性能,从而评估其效率。


4.2 不同时间复杂度算法对比

我们用具体的例子来说明算法对时间复杂度的影响。

假设有两个数组:找到两个数组中和为目标值的所有数对
arr1 = [1, 2, 3, 4]
arr2 = [3, 4, 5, 6]
目标是找出所有满足 x + y = 7 的数对。

1) 不使用嵌套循环解决问题(排序 + 下标)

我们可以先数组排序,然后使用两个下标(指针)来解决问题。

arr1 = [1, 2, 3, 4]
arr2 = [3, 4, 5, 6]
target = 7

# 排序两个数组
arr1.sort()
arr2.sort()

result = []
i, j = 0, len(arr2) - 1  # 设置两个下标,一个从 arr1 开始,一个从 arr2 末尾

while i < len(arr1) and j >= 0: 
    if arr1[i] + arr2[j] == target:
        result.append((arr1[i], arr2[j]))
        i += 1
        j -= 1  # 找到匹配的后,同时移动两个下标
    elif arr1[i] + arr2[j] < target:
        i += 1  # 当前和小于目标值,增加较小的数字
    else:
        j -= 1  # 当前和大于目标值,减少较大的数字

print("结果:", result)

输出

结果: [(1, 6), (3, 4)]

2) 使用嵌套循环解决问题

arr1 = [1, 2, 3, 4]
arr2 = [3, 4, 5, 6]
target = 7

result = []
for x in arr1:  # 遍历第一个数组
    for y in arr2:  # 遍历第二个数组
        if x + y == target:  # 检查是否满足条件
            result.append((x, y))

print("结果(嵌套循环):", result)

输出

结果(嵌套循环): [(1, 6), (3, 4)]
4.3 算法效率分析:

在这个嵌套循环中,每个外层循环 n 次,内层循环 m次,时间复杂度为:O(nxm)=O(n^2)

若n = m = 1,000 ,循环次数=1,000×1,000=1,000,000,需要执行百万次操作。

当 n = m = 10^6 时,循环次数=10^6×10^6=10^12,需要执行万亿次操作。


而在不使用嵌套循环的算法中:

排序两个数组需要:O(nlog⁡n+mlog⁡m),遍历两个数组的时间复杂度为:O(n+m)

若 n = m = 1,000,排序时间约为 1,000log⁡1,000≈10,000 次操作,遍历时间为 1,000+1,000=2,000次操作。

总循环次数=10,000+2,000=12,000,优化了 99% 以上的计算量。

若 n = m= 10^6,总循环次数=20,000,000+2,000,000=22,000,000,相比万亿级的计算量已经大大减少。


因此在编程时,我们要特别注意:

  • 嵌套循环虽然简单直接,处理日常任务可以使用,但容易因指数增长导致效率低下。
  • 在需要处理大规模数据时,应尽量避免嵌套循环,优化算法效率,减少不必要的重复计算。

5.小结

在本节中,我们一些重要的控制结构,重点是条件判断和循环

️ 循环结构用于重复执行代码,有 for 和 while 两种形式,适合不同场景。

条件判断让程序具备决策能力,if-else 适合复杂逻辑,match-case 则简化多分支选择。

算法效率与时间复杂度密切相关,循环的次数随数据规模增加而快速增长,优化代码能显著提高性能。


http://www.kler.cn/a/505523.html

相关文章:

  • 【RDMA学习笔记】1:RDMA(Remote Direct Memory Access)介绍
  • 数据结构之双链表(C语言)
  • uni-app的学习
  • 前端组件开发:组件开发 / 定义配置 / 配置驱动开发 / 爬虫配置 / 组件V2.0 / form表单 / table表单
  • Node.js - HTTP
  • 【spring mvc】文件上传、下载
  • MySQL(行结构)
  • 校园跑腿小程序---轮播图,导航栏开发
  • 深度学习-85-RAG技术之Faiss搭配合适的model和embedding函数应用示例
  • 【c++】【Linux】堆和栈的区别
  • 81_Redis经典面试问题
  • 大语言模型训练
  • Yantra:一个基于.Net跨平台JavaScript开源引擎
  • PyCharm文档管理
  • stable diffusion 量化学习笔记
  • 【北京迅为】iTOP-4412全能版使用手册-第七十三章 Qt信号和槽
  • 基于R计算皮尔逊相关系数
  • 电脑有两张网卡,如何实现同时访问外网和内网?
  • Android-目前最稳定和高效的UI适配方案
  • redhat安装docker 24.0.7
  • CV(10)--目标检测
  • 解决Django SimpleUI应用中的CSRF验证失败问题
  • 【Leetcode 热题 100】295. 数据流的中位数
  • 深度学习每周学习总结R4(LSTM-实现糖尿病探索与预测)
  • C# 下 SQLite 并发操作与锁库问题的 5 种解决方案
  • 【Mock】前端er 如何优雅快速搭建Mock服务