python UNIT 3 选择与循环(2)

news2024/12/26 2:13:58

目录

1。循环的优化

经典优化分析:

未优化的代码:

细节分析:

优化后的代码:

优化的细节:

性能对比

优化的关键在于:

经典习题讲解:(紫色的解析请重点关注一下)

1。例三

个人代码解析:

总代码演示:

例3-8:

个人代码解析:

总代码演示:

例3-9:

这种题的难度就在于两层循环的起始点和步长等的控制。

个人代码解析:

全部代码展示:

循环变形:

打印效果:


我们先来看一下循环的优化!!!

1。循环的优化

经典优化分析:

优化的核心在于减少循环内不必要的计算,通过将与循环变量无关的操作移到外部,从而提高性能。

未优化的代码:

import time
digits = (1, 2, 3, 4)

T1 = time.perf_counter()
for _ in range(1000):  # 外层循环
    result = []
    for i in digits:           # 第一个内层循环
        for j in digits:       # 第二个内层循环
            for k in digits:   # 第三个内层循环
                result.append(i * 100 + j * 10 + k)  # 在这里进行计算
T2 = time.perf_counter()

print('优化前程序运行时间:%s毫秒' % ((T2 - T1) * 1000))

细节分析:

  • i * 100j * 10 是每次内层循环中都需要计算的部分,但实际上,ij 的值在每个循环中是固定的。因此,它们每次重复计算没有意义。
  • 也就是说,在每一次 ij 循环不变时,我们多次重复计算了 i * 100j * 10。这个操作浪费了时间。

优化后的代码:

import time
digits = (1, 2, 3, 4)

T3 = time.perf_counter()
for _ in range(1000):  
# 外层循环
    result = []
    for i in digits:        
  # 第一个内层循环
        i = i * 100            # 将 i * 100 提取到第二层循环外部
        for j in digits:       # 第二个内层循环
            j = j * 10         # 将 j * 10 提取到第三层循环外部
            for k in digits:   # 第三个内层循环
                result.append(i + j + k)  # 优化后的计算
T4 = time.perf_counter()

print(f'优化后程序运行时间:{(T4 - T3) * 1000}毫秒')

优化的细节:

  1. 提取计算到外层循环

    • 在未优化的版本中,i * 100j * 10 在每次 k 的循环时都被重复计算。而实际上,i * 100 在每次 i 变化后才会变化,所以我们可以把它提取到 for j in digits: 循环的外部。
    • 同理,j * 10 只需要在每次 j 变化时计算一次,我们将它提取到 for k in digits: 循环的外部。

    优化后的计算公式变成了 i + j + k,其中 ij 预先乘好了系数,避免了重复计算。

  2. 减少了计算量

    • 通过提前计算 i * 100j * 10,我们在最内层的 k 循环中避免了这两项乘法操作。
    • 在内层循环次数非常多的情况下(例如这里的 1000 * 4 * 4 * 4 = 64000 次),减少每次循环的计算量会显著提升效率。

性能对比

  • 优化前:循环中每次都重复进行 i * 100 + j * 10 + k 的运算,时间为 38.0651 毫秒。
  • 优化后:通过将乘法移出循环,每次只进行 i + j + k 的简单加法运算,时间降到了 24.8886 毫秒。

优化的关键在于:

  • 减少循环中的重复计算如果某些计算可以在循环外部完成,不依赖于内部的循环变量,则应当提取到外层循环。
  • 减少运算次数乘法比加法的计算开销大,所以将乘法移出内层循环,改为在外层计算一次,能有效提升性能。

经典习题讲解:(紫色的解析请重点关注一下)

1。例三

虽然已经有答案了,但是我想说的是这个答案不是非常标准,有一个隐藏的bug!!!

个人代码解析:

num = 0;
scores = 0;

作用:初始化两个变量。

  • num:用于计数有效的成绩输入(即学生人数)。
  • scores:累加所有输入的成绩,用于后续计算平均成绩。


ret = 0;
while 1:

作用:进入一个无限循环,直到通过 break 语句显式退出。

  • 1表示循环条件永远为真,因此这个循环会不断执行,直到用户输入退出条件(Q 或 q)。和上面的True一个意思


    x = input("请输入学生成绩(按(Q或q结束):)")

作用:使用 input() 获取用户输入的成绩。

  • 使用input函数充当输入函数用户的输入被赋值给变量 x。输入的内容总是字符串类型,因此后续可能需要进行类型转换。


    if (x == 'Q' or x == 'q'):
        break

作用:检查用户是否输入了 Q 或 q。

  • 如果用户输入的是 Q 或 q,则终止循环(使用 break),结束成绩录入过程。


    # if (x.upper() == 'Q'):
    #     break

upper()函数的作用是将一个字符串的全部字符转换成大写的,原本就是大写的不变,这里使用这个就避免了大小写要辨别两次的问题。
    if (float(x) < 0):
        continue

作用:将用户输入的 x 转换为浮点数,并检查是否为负数。

  • 如果用户输入了负数,程序会跳过当前循环,不进行成绩累加和人数统计,直接进入下一次循环(通过 continue 跳过后续代码)。


    num += 1# python里面没有++自增的这个用法
    scores += float(x)

  num += 1:学生人数计数器 num 增加 1,表示记录了一个有效的成绩。

  scores += float(x):将用户输入的成绩(转换为浮点数)加到 scores 中,累积所有输入的成绩。
if (num == 0):
    print(f'学生人数={num}, 平均成绩={scores}')

作用:在输入结束后,检查是否有有效成绩(即检查学生人数 num 是否为 0)。这里正是图片答案丢失的点,加上这个if判断可以有效解决这个bug

  • 如果 num 为 0,说明用户没有输入任何有效成绩(没有录入任何非负数的成绩),程序输出提示“没有有效成绩输入”。
    else:
        print(f'学生人数={num}, 平均成绩={scores / num}')

作用:如果有有效成绩(num 不为 0),则计算并输出平均成绩。

  • scores / num:将总成绩除以学生人数,计算平均成绩。
  • 使用 f-string 格式化输出,显示学生人数和平均成绩。

总代码演示:

num = 0;
scores = 0;
ret = 0;
while 1:
    x = input("请输入学生成绩(按(Q或q结束):)")
    if (x == 'Q' or x == 'q'):
        break
    # if (x.upper() == 'Q'):
    #     break

    if (float(x) < 0):
        continue
    num += 1# 没有++
    scores += float(x)
if (num == 0):
    print(f'学生人数={num}, 平均成绩={scores}')
else:
    print(f'学生人数={num}, 平均成绩={scores / num}')

例3-8:

这个题的解法精妙之处在于使用了字典进行存储个数。

个人代码解析:

scores = [89, 70, 49, 87, 92, 84, 73, 71, 78, 81, 90, 37, 77, 82, 81, 79, 80,
          82, 75, 90, 54, 80, 70, 68, 61]

  作用:定义一个包含多个学生成绩的列表 scores。这里列表相当于数组来用了

  列表内容:包含 24 个整数,代表不同学生的考试分数。
groups = {'优秀' : 0, '良':0, '中':0, '及格':0, '不及格':0}

  作用:初始化一个字典 groups,用于统计不同分数段的学生人数。

  字典内容

  • '优秀':统计分数 >= 90 的学生人数,初始值为 0。
  • '良':统计分数在 80 到 89 的学生人数,初始值为 0。
  • '中':统计分数在 70 到 79 的学生人数,初始值为 0。
  • '及格':统计分数在 60 到 69 的学生人数,初始值为 0。
  • '不及格':统计分数 < 60 的学生人数,初始值为 0。

这里等级和人数是构成对应关系的,这种对应关系有的KV模型的意思,我们现今所学的有数据构成这种KV关系的就只有字典了
for score in scores:

作用:使用 for 循环遍历 scores 列表中的每个分数,将每个分数赋值给变量 score。
    if score >= 90:
        groups['优秀'] += 1

作用:检查当前的 score 是否大于或等于 90。

  • 如果是,则将 groups 字典中 '优秀' 的值加 1,表示又增加了一个优秀的学生。


    elif score >= 80:
        groups['良'] += 1

作用:如果上一个条件不满足,则检查 score 是否在 80 到 89 之间。

  • 如果是,将 '良' 的值加 1。


    elif score >= 70:
        groups['中'] += 1

作用:如果上一个条件也不满足,检查 score 是否在 70 到 79 之间。

  • 如果是,将 '中' 的值加 1。


    elif score >= 60:
        groups['及格'] += 1;

作用:检查 score 是否在 60 到 69 之间。

  • 如果是,将 '及格' 的值加 1。


    else:
        groups['不及格'] += 1;

作用:如果以上条件都不满足,说明 score 小于 60。

  • 将 '不及格' 的值加 1,统计不及格的学生人数。


print("groups = ", groups)

  作用:输出 groups 字典的内容,显示各个分数段的学生人数。

  输出格式:使用 print() 函数,前面添加了 "groups = " 作为描述,后面跟着字典内容。

print可以打印任何类型的数据

在循环部分有人会写成这个样子,也可以的,就是没有利用到条件直接的排除性,但是需要考虑两边的and的边界问题,也注意一下逻辑与的使用,python没有&&这个在C++表示逻辑与的字符

for score in scores:
    if score >= 90 and score <= 100:
        groups['优秀'] += 1
    elif score >= 80 and score < 90:
        groups['良'] += 1
    elif score >= 70 and score < 80:
        groups['中'] += 1
    elif score >= 60 and score < 70:
        groups['及格'] += 1;
    else:
        groups['不及格'] += 1;

总代码演示:

scores = [89, 70, 49, 87, 92, 84, 73, 71, 78, 81, 90, 37, 77, 82, 81, 79, 80,
          82, 75, 90, 54, 80, 70, 68, 61]
groups = {'优秀' : 0, '良':0, '中':0, '及格':0, '不及格':0}
for score in scores:
    if score >= 90:
        groups['优秀'] += 1
    elif score >= 80:
        groups['良'] += 1
    elif score >= 70:
        groups['中'] += 1
    elif score >= 60:
        groups['及格'] += 1;
    else:
        groups['不及格'] += 1;
print("groups = ", groups)

例3-9:

这种题的难度就在于两层循环的起始点和步长等的控制。

个人代码解析:

for i in range(1, 10):

作用:这个循环从 1 到 9(包括 1,不包括 10)迭代,i 将取这些值之一。
    for j in range(1, i + 1):

作用:这是一个嵌套循环,j 从 1 到 i(包括 i)迭代。随着 i 的增加,j 的范围也会增加。
        print(f'{i} * {j} = {i * j : 2}', end = ' ')

作用:打印乘法表达式 i * j 的结果,格式化输出。{i * j : 2} 意味着结果的宽度至少为 2。格式化打印,end = ' ':这使得打印不换行,而是用空格分隔。
    print()
作用:在内层循环结束后打印一个换行符,以便为下一个 i 的输出创建新的一行。

这部分代码打印一个标准的乘法表。每一行对应一个数字 i,显示了从 1 到 i 的乘法结果。
print()

作用:打印一个空行,以便在两个乘法表之间有一个间隔。
for i in range(1, 10):

作用:与之前相同,i 从 1 到 9 迭代。
    for j in range(i, 10):

  作用:这个嵌套循环从 i 到 9(包括 9)迭代,打印乘法表达式。

  示例:当 i = 3 时,j 将取值 3, 4, 5, 6, 7, 8, 9。由于可以观察到上三角形式打印每行开始j的值都等于i所以j的循环开始条件就是j == i
        print(f'{i} * {j} = {i * j : <2}', end='  ' * 4)

  作用:打印乘法表达式 i * j 的结果,格式化输出。{i * j : <2} 表示结果左对齐,宽度至少为 2。

 {i*j:2<} 表示计算 i*j 并输出其结果,确保输出的宽度至少为 2 个字符,并且左对齐。

  如果结果的字符数小于 2,就在右侧填充空格;如果字符数大于 2,则不做处理。

    请区别于{i*j:<2},所以为了保证前面对齐我们要使用<2。

  end=' ' * 4:这个地方的 end 参数实际上是空格字符。' ' * 4 会创建一个字符串 ' '(四个空格),因此在每个乘法表达式之后会添加四个空格。
    print()

作用:在内层循环结束后打印一个换行符,以便为下一个 i 的输出创建新的一行。

这部分代码打印了另一种格式的乘法表,每一行显示了 i 乘以从 i 到 9 的结果,并且每个乘法表达式之间用四个空格分隔。

全部代码展示:

for i in range(1, 10):
    for j in range(1, i + 1):
        print(f'{i} * {j} = {i * j : 2}', end = ' ')
    print()

print()
for i in range(1, 10):
    for j in range(i, 10):
        print(f'{i} * {j} = {i * j : <2}', end=' ' * 4)
    print()

循环变形:

变形:(观察变形过程)

for i in range(1, 10):

for k in range(1, i):

  作用:这个嵌套循环在每一行开始前,打印空格。k 从 1 到 i - 1 迭代,负责输出前导空格。

  示例:当 i = 3 时,k 将取 1, 2,这意味着会打印两个空格。多了每行之前会打印一定量的空格的操作。

        print(' ' * 6, end = ' ')

    for j in range(i, 10):

        print(f'{i} * {j} = {i * j : <2}', end=' ')

print()

打印效果:

相比之下,就是每行前面多了很多有规律的空格。

预知后事如何请持续关注博主的动态。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2181403.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python发送邮件附件全攻略:从设置到发送!

Python发送邮件附件的详细步骤&#xff1f;如何利用Python发信&#xff1f; Python作为一种强大的编程语言&#xff0c;提供了丰富的库来帮助我们自动化这一过程。AokSend将详细介绍如何使用Python发送邮件附件&#xff0c;从基础设置到实际发送&#xff0c;带你一步步掌握这一…

【计算机网络】数据链路层理解

文章目录 一、引言二、MAC地址三、以太网四、交换机五、ARP与RARP1、ARP2、RARP 一、引言 数据链路&#xff0c;有时也指以太网、无线局域网等通信手段。数据链路层的协议定义了通过通信媒介互联的设备之间传输的规定。通信媒介包括双绞线电缆、同轴电缆、光纤、点播以及红外线…

值得去公司(完整榜单)

值得去公司 近日&#xff0c;脉脉出了一份《职得去公司》榜单&#xff1a; 前三名是 TAM&#xff08;老牌巨头百度日常掉队&#xff09;。 大家肯定好奇这个榜单怎么统计出来的。 这上面写的是根据「雇主指数」进行排名&#xff0c;广义的雇主指数包括了多个维度&#xff0c;包…

PasteForm最佳CRUD实践,实际案例PasteTemplate详解之3000问(三)

作为“贴代码”力推的一个CRUD实践项目PasteTemplate,在对现有的3个项目进行实战后效果非常舒服&#xff01;下面就针对PasteForm为啥我愿称为最佳CRUD做一些回答: 哪里可以下载这个PasteForm的项目案例 目前“贴代码”对外使用PasteForm的项目有"贴Builder(PasteSpide…

Redis: 主从复制读写分离环境搭建

概述 Redis 的单机模式实际上就是在一个服务器上装了一个单节点的Redis通过简单的配置和简单的命令启动起来就可以使用这种搭建环境&#xff0c;不保证高可用的情况下&#xff0c;完全没有问题如果说你的项目必须要具备高可用&#xff0c;而且 Redis 也要提供更高的性能这个单…

java项目实现钉钉异常告警实时监控

最近有个小伙伴问我&#xff0c;我们的项目核心业务的地方总是有异常&#xff0c;虽然有打印日志&#xff0c;但不能立马通知我&#xff1b;所以今天我就教大家如何实现异常报警实时提醒 1.需要有钉钉 自己新建的企业用户 2.建一个群&#xff0c;需要有三人以上&#xff1b;…

yolov8/9/10模型在仪表盘、指针表检测中的应用【代码+数据集+python环境+训练/应用GUI系统】

可视化训练系统 可视化应用系统 yolov8/9/10模型在仪表盘、指针表检测中的应用【代码数据集python环境训练/应用GUI系统】 背景意义 随着科学技术的快速发展&#xff0c;机器视觉以及人工智能等技术逐渐从理论走向实践&#xff0c;并在各个领域得到广泛应用。机器视觉检测系统…

TCP CUBIC 曲线对 BIC 折线的拟合

bic 旨在对 reno 改进&#xff0c;用二分逼近替换线性遍历逼近&#xff0c;时间规模从 O ( W m a x ) O(W_{max}) O(Wmax​) 下降到 O ( ln ⁡ W m a x ) O(\ln {W_{max}}) O(lnWmax​)&#xff0c;这是本质&#xff0c;而 cubic 可以看作对 bic 的 bugfix&#xff0c;解除了…

新书速览|MySQL 9从入门到性能优化:视频教学版

《MySQL 9从入门到性能优化:视频教学版》 本书内容 MySQL是流行的关系数据库管理系统之一&#xff0c;由于其体积小、速度快、总体拥有成本低、开放源码等特点&#xff0c;一般中小型企业甚至大型互联网企业的应用开发都选择MySQL作为数据库。《MySQL 9从入门到性能优化:视频教…

【经验分享】自动化测试框架实战

一、什么是自动化测试框架 在了解什么是自动化测试框架之前&#xff0c;先了解一下什么叫框架&#xff1f;框架是整个或部分系统的可重用设计&#xff0c;表现为一组抽象构件及构件实例间交互的方法;另一种定义认为&#xff0c;框架是可被应用开发者定制的应用骨架。前者是从应…

「iOS」——KVC

iOS学习 前言KVC模式KVC设值KVC取值KVC使用keyPathKVC处理异常处理不存在的key处理nil异常 KVC处理字典KVC高阶消息传递 总结 前言 对KVC模式的简单学习和总结。 KVC模式 KVC&#xff08;Key-Value Coding&#xff0c;键值编码&#xff09;是一种通过字符串来访问对象属性的机…

详解Linux文件系统

先来研究一下磁盘&#xff1a; LBA 磁头面数 所有磁头是共进退的。 每个扇区的大小假设为&#xff1a;512 磁盘的总容量&#xff1a;盘面*t*s*512 数组的下标范围&#xff1a;盘面*t*s LBA&#xff1a;xxx 假设xxx为LBA地址 xxx/1000h 及为h号盘面 xxx/100c 及c号磁道…

国产化框架PaddleYOLO结合Swanlab进行作物检测

1. 项目介绍 粮食安全&#xff0c;作为人类生存与发展的基石&#xff0c;始终是全球关注的焦点。它不仅仅关乎粮食的充足供应&#xff0c;更涉及粮食的质量安全、营养健康以及可持续生产等多个维度。在全球化、气候变化和资源环境约束日益加剧的背景下&#xff0c;如何确保粮食…

ComfyUI物品移除讲解

实现效果 一、下载插件 comfyui inpaint nodes 提供重绘功能节点&#xff0c;效果比自带的好很多 官方介绍 使用ComfyUI更好地进行修补的节点&#xff1a;用于SDXL&#xff0c;LaMa&#xff0c;MAT和各种其他工具的Foocus修补模型&#xff0c;用于预填充修补和去除区域。 插件…

Android调用科大讯飞语音转写 API以及解析踩坑之旅

需求 需要对本地音频文件&#xff0c;调用科大讯飞的api进行转文字&#xff0c;本来呢&#xff0c;以为很简单&#xff0c;结果坑不少。 语音转写 API 文档 坑1&#xff1a;解析 下载demo&#xff0c;代码也挺简单&#xff0c;放到idea中&#xff0c;替换一下key&#xff0c…

基于Springboot+Vue的网上书店(含源码数据库)

1.开发环境 开发系统:Windows10/11 架构模式:MVC/前后端分离 JDK版本: Java JDK1.8 开发工具:IDEA 数据库版本: mysql5.7或8.0 数据库可视化工具: navicat 服务器: SpringBoot自带 apache tomcat 主要技术: Java,Springboot,mybatis,mysql,vue 2.视频演示地址 3.功能 在这个…

用户体验测试——21条UX设计原则

根据心理学的研究和发展,对应理论不断被完善到用户体验设计领域,以下21条UX设计原则即为心理学在用户体验设计中的应用,在设计和测试中应用这些原则,可以提高用户体验质量特性,如下所示: 21条UX设计原则 有效性 特斯勒定律(最小复杂度定律) 这个定律也被称为“复杂性…

数据转换新利器,开启企业高效之路

Maria是 S 公司的采购专员&#xff0c;最近需要进行公司设备的采购&#xff0c;这可让她犯了难&#xff1a;公司多个部门提交采购申请&#xff0c;但每个部门都有着不同的需求。一时间她就收到了大量的申请单&#xff0c;却难以高效整合处理&#xff08;比如哪些申请可以合并采…

环境变量

见一见环境变量&#xff1a; 查看环境变量的命令 命令行&#xff1a; echo &PATH echo &HOME env ps ajx ps aux ps -f -o pid code.c中获取环境变量 main&#xff08;char* env[]&#xff09; char* getenv&#xff08;env_name&#xff09; 本地变量 shell…

App模拟下载场景的demo

摘要 目的&#xff1a;提供一个稳定的下载场景&#xff0c;可以手动触发和定时触发下载&#xff0c;每次下载相同大小文件&#xff0c;研究下载场景的功耗影响 原理&#xff1a;把电脑当做服务器&#xff0c;手机测试App固定下载电脑存放的某个XXXMB的大文件&#xff0c;基于…