2.6流程控制语句
2.6.3循环结构语句
循环:周而复始的做某件事
编程语言中对一直重复做某件事情没有终止的情况下称为死循环,但编程中进制
在编程语言中见到的循环通常是两种情况:
-
明确循环次数【做几次后不做了】
-
明确循环条件,到某一条件停止循环
Python为这两个场景的循环提供了对应的循环机制,分别是
for-in循环,应用于明确循环次数的
本质是在遍历容器型数据,【遍历:将容器中的数据从左向右逐个取出】,容器中有几个数据,for-in包含的操作就被被执行几次
语法: for 变量名 in 容器型数据: 重复操作的代码块
解读:重点在于in[进入],进入到容器中获取数据
1. 有数据,获取出来赋值给变量名,然后进行重复的操作,再次执行in 2. 没有数据循环结束
eg: # for-in是来遍历容器型数据 # 现在接触的只有字符串,其中的元素是字符[长度为1的字符串称为字符] for ch in 'hello': print(ch) # h e l l o """ 遍历容器常规的做法: 1. 对容器中的数据进行转换 2. 对容器中的数据进行过滤 """ # 字符串也能用应用算术运算符的加号, 应用在字符串中完成的是拼接 s = 'abc' s1 = 'ABC' res = s + s1 print(res) # abcABC s += s1 print(s) # abcABC
practice: # 将s中的小写英文字母转化成大写,其他不变 news = '' # 需要定义一个新的变量 用来接受最终的变化 for c in s: if 'a' <= c <= 'z': # 对c的值进行判断 是否为小写字母 news += chr(ord(c) - 32) # 变成大写 # 用+=的原因:因为是一个一个拿出来的,所以需要一个一个运算 else: news += c # 后面那个+=:因为等于是赋值,所以需要用+=进行拼接 print(news) # ABCABC
# 将字符串中的数字符号提取出来 s2 = 'good123nice321' new_s = '' # 定义一个新的字符串 设置空字符串 # 遍历 逐个获取 for c1 in s2: # c1是字符串类型 是一个字符 带着'' if '0' <= c1 <= '9': # 判断是否是数字符号 # 比较的时候需要加上引号,因为c1是字符串类型的,不带引号的就是一个可以算术运算的数字 new_s += c1 print(new_s)
# s4 = 'Hello, 大家好,欢迎大家来到Python2304' 提取其中的英文字母与汉字 s4 = 'Hello,大家好,欢迎大家来到Python2304' new1_s = '' for y in s4: if 'a' <= y <= 'z' or 'A' <= y <= 'Z' or '\u4e00' <= y <= '\u9fa5': new1_s += y print(new1_s) # Hello大家好欢迎大家来到Python
统计字符串中字符的个数: # 需要一个计数器 拿一个符号 计数器+1 s4 = 'Hello,大家好,欢迎大家来到Python2304' count = 0 # 遍历 逐个获取 for c2 in s4: count += 1 print(count) # 统计英文字母的个数 letter_count = 0 # 英文字母的计数器 for c3 in s4: if 'a' <= c3 <= 'z' or 'A' <= c3 <= 'Z': letter_count += 1 print('英文字母的个数', letter_count) # 统计英文字母的个数、数字的个数、汉字的个数、其他字符的个数 count = 0 count2 = 0 count3 = 0 count4 = 0 for n in s4: if 'A' <= n <= 'Z' or 'a' <= n <='z': count += 1 elif '0' <= n <= '9': count2 += 1 elif '\u4e00' <= n <= '\u9fa5': count3 += 1 else: count4 += 1 print(count,count2,count3,count4)
while循环,应用于明确循环结束条件
语法: while 条件判断: 重复操作的代码块
解读:判断条件是否成立
-
条件成立,执行重复的操作,再次判断条件是否成立。
-
条件不成立,循环结束。
range功能
用来产生等差数列的,这个结果也是容器型的数据,是range类型的
递增或递减【递增或者递减的数据的差值-步长,在整个数据序列中是一致的】
注意:range只能产生整数的等差数列
格式1:range(stop结束值) 序列的数值是从0开始步长为1的递增到stop[不包含]的数列 eg:range(10)===> 0 1 2 3 4 5 6 7 8 9 格式2:range(start,stop) 序列中的数值是从start[包含]开始步长为1的递增到stop[不包含]的数列 比如: range(1, 11) ===> 1 2 3 4 5 6 7 8 9 10 格式3: step为正数 表示递增 start < stop step为复数 表示递减 start > stop 从start[包含]开始 以步长 step 递增或递减到stop[不包含]的数列 eg:range(1,11,2)===>1 3 5 7 9 range(1,100,10)===> 1 11 21 31 41 51 61 71 81 91 [可以理解为100以内 个位数为1的数据] range(10,0,-2)===> 10 8 6 4 2
# 密码输入,设定最大输入三次 # 因为循环次数明确,所以使用for-in循环 for p in 'abd' psw = input('') print(psw) 或 for i in range(3) # 0, 1 ,2 print('password:') # 如果需要某个操作执行100次 # 需求从1数到100 for i in range(1, 101, 1): print(i) # 数据变化规律是在range操作中体现出来的,range(1, 101)从1开始 然后步长为1 除了使用range控制循环次数 本身也是在产生等差数列,如果需要数据参与运算 range用起来方便
practice: 1. 输入一个整数,计算这个数的阶乘 比如5! = 5 * 4 * 3 * 2 * 1 num = int(input('shu:')) total = 1 for i in range(1, num+1, 1): total *= i print(total) 2. 求1-100中个位数是3并且是9的倍数的累加和 total = 0 for i in range(3, 101, 10): if i% 9 == 0: total += i print(total) 3. 求1-100中是5的倍数并且也是3的倍数的数据的个数 count = 0 for i in range(1, 101, 1): if i% 15==0: count += 1 print(count) 或 for e in range(15, 101. 15) print(e)
for-in循环能做的 while循环也能做,但是没有for-in简洁,while循环需要把规律写成代码,因为while不是在遍历容器,没有使用range的功能
语法: while 条件判断: 重复操作的代码块 1. 重复操作的是事情是什么 2. 做这件事情的条件是什么 eg: 打印1到100, 1.重复的操作就print(打印) 2.做这件事情的条件,打印到100即停止 只要数据没有到达100,就得一直打印 如果完成这个需求,需要准备以下数据: print(数据)、数据的起始值以及对数据进行变更 # 设置数据起始值 num = 1 # 开启循环机制 while num <= 100: print(num) #变更数据 下个数在当前基础上+1 num= num + 1 print('循环结束')
次数明确的,结合range使用for-in即可
次数不明确的,使用while循环
eg: # 需求: 绳子长2000m, 每次截取剩余绳子长度的四分之一,问截取多少次之后 绳子长度不足5m """ 1. 重复操作的是事情是什么?? 截取绳子 每次截取绳子长度的四分之一 2. 做这件事情的条件是什么 绳子不足5m停止截取 换句话说:只要绳子长度大于或者等于5m 就得一直做这件事 数据准备: 绳子的长度 求的次数 需要计数器 """ length = 2000 count = 0 # 计数器 # 开启循环机制 while length >= 5: length *= 3/4 # length = length * 3/4 # 次数+1 count += 1 print(count)
practice: # 折纸问题 一张纸厚度是0.08mm, 问对折多少次 达到珠穆朗玛峰的高度 8848.18m count = 0 height = 0.00008 while height < 8848.18: height = height * 2 count += 1 print(count) # 27 # 一个猴子吃桃子 第一天有2350个桃子,每天吃剩余桃子的一半多一个,问多少天后桃子吃完 count = 0 total = 2350 while total >= 0: total = total - (total/2 + 1) count += 1 print(count) # 11
beak\continue\pass
pass 是代码块占位符,代码块中不能空白的 【那块的逻辑暂时未写 可以使用pass占位】
break和continue都是应用于循环语句中的
-
break 的作用是退出结束其所在的循环语句
-
continue的作用是结束当前执行,回归到条件判断或者in 遍历操作的位置,检测条件是否成立或者容器是否还有数据,条件成立或者是容器中有数据,继续执行下一次,否则结束循环
写while循环的时候可以写while True:[死循环] 按照需求根据变化使用break退出循环
eg: # 青蛙从井底向上爬 井深10m 白天向上爬3m 晚上掉下去1m 问几天爬出来 # 重复的操作 爬+掉 deep = 10 # 井的深度 day1 = 0 # 爬的天数的记录者 while True: day1 += 1 # 开始爬 进行计数 # 白天向上爬 deep -= 3 # 注意要有判断: 白天爬出来了 if deep <= 0: break # 结束循环 # 晚上掉下去 deep += 1 print(day1) # continue 结束当前次 在判定条件是否开启下一次 # 需求: 打印1-10中的偶数 for e in range(1, 11): # 打印的时候判断是否为偶数 if e % 2 == 0: print(e) # 反向思维:可以判断是否为奇数 是奇数 跳过打印 for e1 in range(1, 11): if e1 % 2: # 直接冒号加回车,应用了隐式布尔转换,按照布尔转化规则,非0即为True continue #continue后面的代码被跳过,print不执行 print(e1) # pass for ele in range(1, 100): # 这里的内容没想好写什么 不能直接略过的 pass print('循环结束')
for - else结构[else是否则的意思]
for-in遍历容器,只要容器中有数据,就会进入到循环体在,当且仅当容器里没有数据可遍历时,才会执行else
for i in range(1,6) print(i) else: print('容器里没有数据可遍历了')
break结束循环,达到某种要求强制结束
eg: 1. 判断一个str里是否是纯数字的 s = '1293834' s1 = 'ada23344' # 纯数字,验证需要从头到尾遍历,但是实现起来比较麻烦,可以用反向思维:验证是否不是纯数字,则不用从头遍历到尾。当不是不成立就代表的是 for ch in s1: if not('0' <= ch <= '9'): print(s1,'不是') break # 加break 否则有几个非纯数字,print执行几遍 else: print(s1,'是')
practice: # 判断一个整数是否为质数{大于1的自然数中,因数【只有】1和它本身} # 如果在1和本身之间出现了其他的因数,则不是质数 num = int(input('number:')) if num <= 1: print('不是') else: for ch in range(2, num + 1): # 不用考虑1的情况,因为1肯定在因数里 if num% ch == 0: print('不是') break # 必须加break否则会选出所有的因数输出(不是),遍历完成之后输出一个(是) else: print('是') 或 """ 6 2*3 8 2*4 9 3*3 25 5*5 36 2*18 3*12 4*9 6*6 64 2*32 4*16 8*8 观察一下 拆解的因数 36 因数拆解 左边的数据 <= 6 右边的数据 >= 6 当左边的数据有成立的 右边的不需要判定了 数据再缩小范围 只验证<=6的即可 6是36的开平方的值 所以范围可以设置为 2到数据开方+1 """ num = int(input('请输入一个整数:')) if num <= 1: print(num, '不是质数') else: for m in range(2, int(num ** (1/2)) + 1): # 开方的结果是浮点型的 因此这里需要转成整型 if num % m == 0: print(num, '不是质数') break else: print(num, '是质数')
循环语句嵌套
场景:重复的操作被重复的执行
注意:尽量避免过多的循环嵌套,建议最多就3层
eg: # 横向打印六颗星一次打印一个 for i in range(6): print(*, end=' ') # 换行再次打印六颗星 for c in range(3): for y in range(6): print(*, end=' ') print() # print什么都不打印就等于一个换行符,因为里面有默认的end='\n'
有行和列就要用循环嵌套,外层是行内层是列
有些情景:列的个数需要行找规律,eg:打印形状。
* ** *** **** ***** 每一行的列数等于当前行号 for r in range(1,6): # 行号 1 2 3 4 5 # 内层:每一行的列数 容器中有几个数据 for c in range(r): print(*, end=' ') print()
practice: ***** **** *** ** * for r in range(5, 0, -1): for c in range(r): print('*', end=' ') print() 或 for r1 in range(1,6): for c1 in range(6 - r1): print('*', end=' ') print()
practice: 99乘法表 for r in range(1, 10, 1): # [1,2,3,4,5,6,7,8,9]行号 # 列的容器 for r1 in range(1, r+1, 1): print(r1, '*', r, '=', r*r1, end=' ') print()
外层循环中 容器的数据代表的是行号
内层循环中 容器中的数据代表的是列号
百元百鸡问题、白马百担问题 公鸡5元一只,母鸡3元一只,小鸡3只一元,用一百块买一百只鸡 穷举法【把每种组合都列举一下 查找满足需求的】 假设 100元全部买鸡 公鸡 最多买20只 range(1, 20) 母鸡 最多33只 range(1, 34) 小鸡 最多100只(因为规定就100只)range(3, 100, 3) 公鸡 母鸡 小鸡 1 1 3 2 1 6 # 公鸡的购买只数 for g in range(1,20): # 母鸡的 for m in range(1,34): # 小鸡的 for x in range(3,100,3): # 判断 if g + m + x ==100 and 5*g + 3*m + x//3 == 100 print(g, m, x) # 计算了两万多次 简化 # 公鸡的购买只数 for g in range(1,20): # 母鸡的 for m in range(1,34): # 小鸡的 x = 100 - g - m if x%3==0 and 5*g + 3*m + x//3 ==100 # 循环了六百多次
practice: # 100匹马,驼100担货,大马3,中马2,2匹小马1,问大中小马个各多少 for i in range(1, 34): for m in range(1, 50): l = 100 - i - m if l% 2 == 0 and i*3+m*2+l//2 == 100: print(i,m,l)
斐波那契数列: """ F(1) = 1 F(2) = 1 F(n) = F(n-1) + F(n-2) (n>=3) 公式是由一堆兔子推出来的 需求: 第一个月有一对兔子,这对兔子 从第三个月开始 每个月都会生一对小兔子, 小兔子从出生开始第三个月 每个月都会生一对小兔子 假设兔子不死,问N个月后兔子的对数是多少 """ # 键盘录入一个月份 求这个月份对应的兔子的对数 """ 规律中是有两个已知项的 【1月和2月兔子的对数】 这个已知项就是数据计算的起始值 """ # 记录上个月的兔子数 last_month = 1 # 记录上上个月 before_last_month = 1 # 当前月份的兔子数 current = 1 # 输入月份 month = int(input('请输入月份:')) # 遍历 if month == 1 or month == 2: print('兔子的对数为', current) else: for m in range(3, month + 1): # 当前月份的兔子数 current = last_month + before_last_month # 相求下个月的 上个月的兔子数与上上个月的兔子数的记录者发生变化 # 上个月的赋值为当前月的数据 上上个月的为上个月的数据 last_month, before_last_month = current, last_month print('兔子的对数为', current) 或 # 简洁版,只把1月份当做已知项 # F(n) = F(n-1) + F(n-2) # 本月的数据 = 上个月的数据+上上个月的数据 last = 0 # 上个月的数据信息 【已知项是1月份 上个月0月份 没有数据 将值设置为0】 current1 = 1 # 1月份 # 现在到了2月份了 上个月就变成1月份 current1, last = last + current1, current1 # current1记录的2月数据 last记录的是1月的数据 # 现在是3月份了 上个月得是2月 current1, last = last + current1, current1 # current1记录的3月数据 last记录的是2月的数据 last0 = 0 # 现在是0月份的数据 count = 1 # 现在是1月份的数据 if month == 1: print('兔子的对数', count) else: for m0 in range(2, month + 1): count, last0 = count + last0, count print('兔子的对数', count)