目录
前课复习
程序的控制结构
一、程序的分支结构
1、单分支结构
2、二分支结构
3、多分支结构
4、条件判断及组合
5、程序的异常处理
总结
二、实例5:身体质量指数BMI
1、问题分析
2、思路1:分别计算并给出国际和国内BMI分类
3、思路2:混合计算并给出国际和国内BMI分类
4、举一反三
三、程序的循环结构
1、遍历循环:保留字 for in 构成
2、无限循环(条件循环):保留字 while
3、循环控制保留字:break 和 continue
4、循环的高级用法(通过else给奖励)
总结
四、模块3:random库的使用
1、基本随机数函数
2、扩展随机数函数
五、实例6:圆周率的计算
1、公式计算
2、蒙特卡罗方法计算
3、举一反三
前课复习
if - elif -else 分支结构
for i in range 循环结构
程序的控制结构
- 顺序结构:程序按照线性顺序逐渐执行的结构
- 分支结构:程序根据条件有选择的向程序运行方向执行的结构
- 循环结构:程序根据一定条件向程序运行之后,也就是程序曾经执行过方向返回执行的结构
一、程序的分支结构
1、单分支结构
分支结构是根据判断条件结果而选择不同向前路径的运行方式
guess = eval(input())
if guess == 99:
print("猜对了")
判断条件可以直接使用真假来表示,只要见到 if True,后面的语句就会被执行
if True:
print("条件正确")
2、二分支结构
根据条件判断的不同而选择不同执行路径的一种结构
guess = eval(input())
if guess == 99:
print("猜对了")
else:
print("猜错了")
if True:
print("语句块1")
else:
print("语句块2") # 事实上这部分永远不会被执行
二分支结构除了简单的 if else 之外,还需知道一种紧凑形式
- 仅适用于表达简单逻辑的二分支结构的一种紧凑方式
- 优点:简洁
- if else 对应的输出不是语句,而是表达式。所谓的表达式是语句的一部分,简单理解为:语句为带赋值形式的、有等号构成的语句,而 if else 的紧凑形式不支持这种带等号的赋值形式,它只支持表达式形式,也就是语句中的一部分
当条件成立了返回表达式1的信息,当条件不成立else后的表达式2被执行
guess = eval(input())
print("猜{}了".format("对" if guess == 99 else "错"))
上例中的 “对” “错” 都是表达式,而不是带等号的赋值形式
3、多分支结构
根据多个条件来选择不同语句块运行的一种分支结构
- 注意多条件之间的包含关系
- 注意变量取值范围的覆盖
例:对不同分数分级的问题
score = eval(input())
if score >= 90:
grade = "A"
elif score >= 80:
grade = "B"
elif score >= 70:
grade = "C"
elif score >= 60:
grade = "D"
print("输入成绩属于级别{}".format(grade))
4、条件判断及组合
分支语句中需要大量的条件判断,Python提供了一些操作符来对条件进行判断,并产生真或假的结果
除了操作符之外,Python 也提供了三个用来对条件进行组合的保留字
- x and y:条件x成立,条件y也成立,那么经过and操作符获得的结果才是真值
- x or
- not
guess = eval(input())
if guess>99 or guess<99:
print("猜错了")
else:
print("猜对了")
if not True: # 表达假的逻辑,即False
print("语句块2") # 永远不会被执行
else:
print("语句块1") # 只会执行语句块1
5、程序的异常处理
- 异常处理有两种非常基本的使用方法,使用保留字 try 和 except
- 进一步也可以指定异常处理的异常类型,在except后面直接增加异常的名字(Python中预定义的)
- 标注异常类型后,仅响应该类型异常。异常类型名字是Python内部定义的,等同于变量,不需要对它增加字符串表示
例子:
try:
num = eval(input("请输入一个整数:"))
print(num**2)
except:
print("输入不是整数")
try:
num = eval(input("请输入一个整数:"))
print(num**2)
except NameError:
print("输入不是整数")
异常处理的高级使用方法
- 首先执行语句块1的一部分代码,若它不发生异常,奖励性地让它执行语句块3,;若发生异常,让它执行语句块2;无论发不发生异常,最后都要执行语句块4
- 这种方式可以增加更多的异常处理相关逻辑,使得异常处理变得非常鲁棒
总结
二、实例5:身体质量指数BMI
1、问题分析
2、思路1:分别计算并给出国际和国内BMI分类
# CalBMIv1.py(国际)
# 用户输入是多元素,建议采用逗号隔开
height,weight = eval(input("请输入身高(米)和体重(公斤)[逗号隔开]:"))
bmi = weight /pow(height,2)
print("BMI数值为:{:.2f}".format(bmi))
who = ""
if bmi < 18.5:
who = "偏瘦"
elif 18.5 <= bmi < 25:
who = "正常"
elif 25 <= bmi <30:
who = "偏胖"
else:
who = "肥胖"
print("BMI指标为:国际'{0}'".format(who))
# CalBMIv2.py(国内)
# 用户输入是多元素,建议采用逗号隔开
height,weight = eval(input("请输入身高(米)和体重(公斤)[逗号隔开]:"))
bmi = weight /pow(height,2)
print("BMI数值为:{:.2f}".format(bmi))
nat = ""
if bmi < 18.5:
nat = "偏瘦"
elif 18.5 <= bmi < 24:
nat = "正常"
elif 24 <= bmi < 28:
nat = "偏胖"
else:
nat = "肥胖"
print("BMI指标为:国内'{0}'".format(nat))
3、思路2:混合计算并给出国际和国内BMI分类
# CalBMIv3.py(混合计算)
height,weight = eval(input("请输入身高(米)和体重(公斤)[逗号隔开]:"))
bmi = weight /pow(height,2)
print("BMI数值为:{:.2f}".format(bmi))
who,nat = "",""
if bmi < 18.5:
who ,nat = "偏瘦" ,"偏瘦"
elif 18.5 <= bmi < 24:
who ,nat = "正常","正常"
elif 24 <= bmi < 25:
who ,nat = "正常","偏胖"
elif 25 <= bmi < 28:
who,nat = "正常","偏胖"
elif 28 <= bmi < 30:
who,nat = "偏胖","肥胖"
else:
who,nat = "肥胖","肥胖"
print("BMI指标为:国际'{0}',国内'{1}'".format(who,nat))
4、举一反三
三、程序的循环结构
1、遍历循环:保留字 for in 构成
遍历某一个结构形成的循环运行方式
- 可以从遍历结构中逐一提取元素,放到循环变量里
- 使用的遍历结构,是一种能够包含多个元素的结构。所谓遍历结构,不是一种特殊的类型,它包含很多种类型
- 每次循环时,能够从遍历结构中提取其中的一个元素,放到前面的循环变量里,去执行下面的语句块,执行后再从遍历结构中提取下一个元素。当遍历结构中的所有元素都放入循环变量,并且都已经循环执行之后,程序退出
遍历循环的应用
- 计数循环(N次) range函数
遍历下面的语句块,执行N次语句块的内容
range(N) 函数产生一个数字序列,这个序列包含N个元素,每个元素都是一个整数(从 0 到N-1),例:
也可以在中间的语句块中不使用变量i - 计数循环(特定次) range函数 range是函数,M、N、K是函数的参数 range(M,N,K) 会产生一个数字序列,从M开始,不到N,到N之前的整数,以K为步长,例:
- 字符串遍历循环
s是一个字符串,c是字符串中的每个字符,能够从字符串中按顺序取出每一个字符放到c中。而针对每一次取出的字符,执行一次语句块,进而产生循环。例: 在打印的每个字符后面增加一个逗号 - 列表遍历循环 ls 为一个列表,遍历列表,将其中的每一个元素拿出来放到 item 变量中,同时执行一次当前的语句块产生循环
- 文件遍历循环
遍历文件的每一行
fi 为一个文件标识符(对一个外部文件,通过Python函数将文件打开,如果该文件是以字符形式打开,就会表示为一个文件的标识的名字。相当于用一个变量来标识系统中的一个文件,这个变量就叫文件标识符) - 元组遍历循环
- 字典遍历循环
- ....
所有 for in 这样可遍历的结构,只要后边的变量或者数据类型是一个由多个元素构成的数据类型,都可以使用 for in 的方式遍历其中的每一个元素,并且根据元素的个数形成相应的循环
2、无限循环(条件循环):保留字 while
由条件控制的循环运行方式
- 不再是遍历某一个结构,而是根据这个条件来进行循环
- 反复执行语句块,直到条件不满足时结束
3、循环控制保留字:break 和 continue
continue 例子
遍历一个字符串,如果这个字符串中出现了T,就不打印T,否则打印其他的所有字符出来
在当次循环体执行时,如果遇到了continue保留字,当次循环就结束,去做下一次循环
break 例子
遇到break,整个循环结束。若程序有两层或更多层循环,break该怎么办呢?
# 最开始给出一个字符串,每次循环将字符串的最后一个字符去掉,打印出字符串
s = "PYTHON"
# 双层循环
while s != "": # 若字符串s不是空字符串
for c in s: # 将字符串中的每一个字符拿出来
print(c,end="")
s = s[:-1] # 去掉s的最后一个字符
一个break保留字仅跳出当前的最内层循环,若有多层循环嵌套,它只跳出内层,外层循环仍然有效
# 取出一个字符串,只要遇到T就停止遍历,将字符串的最后一位去掉,再去遍历,遇到T还停止遍历
s = "PYTHON"
# 双层循环
while s != "": # 若字符串s不是空字符串
for c in s: # 将字符串中的每一个字符拿出来
if c== "T":
break # 仅跳出当前最内层循环(一个break只能跳出一层循环)
print(c,end="")
s = s[:-1] # 去掉s的最后一个字符
4、循环的高级用法(通过else给奖励)
通过else的扩展,能够知道一段循环中是否被break结束
# 无break语句,循环结束后,将打印出正常退出的这段代码
for c in "PYTHON":
if c == "T":
continue
print(c,end="")
else:
print("正常退出")
# 有break,else部分的正常退出语句就不会被执行
for c in "PYTHON":
if c == "T":
break
print(c,end="")
else:
print("正常退出")
总结
四、模块3:random库的使用
1、基本随机数函数
- Python中的随机数采用随机数种子来产生
- 计算机产生随机数,是需要一个随机数种子的,给定一个种子(比如10),再采用梅森旋转算法,就能够根据种子产生一系列的数据,那么这个随机序列是根据种子来唯一确定的,随机序列中的每一个数就是随机数
- 只要种子相同,产生的随机序列,无论是每一个数,还是数之间的关系,都是确定的
- 随机数种子确定了随机序列的产生
- seed:在使用随机数时,可以不调用seed函数,可以直接调用random.random()来产生随机数,不需要使用seed函数。若不使用或不调用seed函数时,将会使用当前操作系统的默认的系统时间作为种子
- random:生成一个从0开始,到1.0之间的随机小数,这个随机小数的产生与种子有关(若用种子10,产生的第一个小数一定是0.57)
也可以不给种子, 直接调用 random 也可以产生随机数,此时默认的种子是当前调用第一次random函数所对应的系统时间
为什么要给种子?
- 若编程中给出了随机种子,那么下一次程序再次运行,只要种子相同,那么产生的随机数也是相同的,对于使用随机数的程序可以复现或再现程序运行的过程,如:
- 若不使用随机数种子,那么它使用的是当前系统时间,而那个时间是精确到微秒的,很难再现,后面产生的程序运行的结果就是完全随机,不可再现;
- 综上,需要再现随机过程就设定种子
2、扩展随机数函数
在random库中,最基本的是seed和random函数,除此之外,random库提供了常用的六个扩展随机数函数
五、实例6:圆周率的计算
1、公式计算
累加求和,累加的变量k从0到无穷大,使用for循环来实现这种累加
代码:
# CalPiV1.py(通过公式计算圆周率的值)
pi = 0
N = 100 # 假设无穷大是N(100)
for k in range(N):
'''若写一段代码特别长,在一行中无法表达,
可以在这段代码中增加\,使代码进行换行,换行后还可以再使用\再进行换行,
且换行之后的代码,它的功能与写在一行是一致的'''
pi += 1/pow(16,k)*( \
4/(8*k+1) - 2/(8*k+4) - \
1/(8*k+5) - 1/(8*k+6))
print("圆周率值是:{}".format(pi))
2、蒙特卡罗方法计算
蒙特卡罗方法(撒点):圆周率本身就是一个圆形,相对于一个正方形来说,相当于圆的面积除以正方形的面积,这个面积之商与圆周率有关系
- 圆的面积如何计算?
- 对一个区域面积向它撒点,每给一个撒点,它随机的可能会出现在这个区域中的任何一个位置上,若撒点的数量十分庞大,而且每一个点又尽可能地随机,那么在圆的面积内部的点就构成了圆的面积,而在整个正方形中的所有撒点就是正方形的面积
- 通过点的数量与整个圆方形中的撒点数量的比值,就能够计算出圆的面积
代码:
# CalPiV2.py(通过蒙特卡罗方法计算圆周率的值)
from random import random
from time import perf_counter # perf_counter函数能够对程序运行进行计时
DARTS = 1000*1000 # 当前在区域中抛撒点的总数量,为100万
hits = 0.0 # 目前在圆的内部的点的数量
start = perf_counter() # 当前系统时间的一个值,启动计时
# 循环撒点的过程,可以描述为一次遍历循环的过程
for i in range(1,DARTS+1): # 对所有点进行抛撒
x,y = random(),random() # 使用x,y变量生成两个随机数的坐标值,random函数返回的是0-1之间的小数值
dist = pow(x**2+y**2,0.5) # 使用这个点到圆心的距离判断其是否在圆内
if dist <= 1.0: # 这个点在圆的内部
hits = hits+1 # 经过撒点之后,在圆的内部出现的点的数量
pi = 4* (hits/DARTS)
print("圆周率值是:{}".format(pi))
print("运行时间是:{:.5f}s".format(perf_counter()-start))
未用公式,只用计算机、随机方式就可以计算pi
3、举一反三
- 一个程序,它的主要运行时间都花在循环上,利用time库的perf_counter方法初步掌握简单的程序性能分析方法
- 在工程中有很多通过蒙特卡罗方法(随机方法)来进行应用的场景