{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 3.7 流程跳转语句"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 3.7.1 pass 语句 "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"pass相当于一个空语句,他不执行任何操作,可用在语法上需要语句,却不需要执行任何操作时,如pass 用作函数或条件语句体的占位符,让你保持在更抽象的层次进行思考。pass 会被默默地忽略: "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"while True:\n",
" pass # 忙-等待键盘中断"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"也常用作为类、函数或条件体的占位符,或者创建占位程序、保证格式完整、保证语义完整等。"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"ename": "SyntaxError",
"evalue": "unexpected EOF while parsing (2399861802.py, line 2)",
"output_type": "error",
"traceback": [
"\u001b[0;36m File \u001b[0;32m\"/tmp/ipykernel_340/2399861802.py\"\u001b[0;36m, line \u001b[0;32m2\u001b[0m\n\u001b[0;31m # 占位,提醒这是一个待完成的函数定义\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m unexpected EOF while parsing\n"
]
}
],
"source": [
"def initlog(a,v):\n",
" pass # 占位,提醒这是一个待完成的函数定义\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 3.7.2 continue"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"continue语句应用于while或for...in<font color=Red>__循环语句__</font>中。 \n",
"一般置于条件判定语句块中,当满足某条件时触发该语句的执行。 \n",
"作用是<font color=Red>__跳过本次循环中continue后面剩余语句__</font>的执行,提前进入下一次循环。 "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 实例 4.9 统计平均成绩 "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"现有一个读文件切分得到的列表,其元素是表示一位同学各门课程成绩的字符串,空字符串表示该门课程因缓考原因导致成绩缺失,请计算并输出该同学的平均成绩。\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"我们知道,缓考导致的成绩缺失并不表示成绩为0,所以计算平均成绩时,应该略过缺失的成绩,只统计正常参加考试获得的成绩,这种情况下,就可以用continue跳过本次循环中剩余程序语句。"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"69\n",
"85\n",
"88\n",
"\n",
"100\n",
"76\n",
"\n",
"95\n"
]
}
],
"source": [
"# 读成绩文件得到各门课程成绩,空字符串表示选课但无成绩\n",
"score = ['69', '85', '88', '', '100', '76', '', '95']\n",
"total = 0 # 总分初值\n",
"amount = 0 # 有成绩的课程数量初值\n",
"for x in score: # 遍历列表,x每次取值为一个字符串\n",
" \n",
" if x == '': # 若当前取值为空字符串\n",
" continue # 跳过当前循环剩余语句,开始下一循环\n",
" total = total + int(x) # 字符串转整数,并累加到总成绩上\n",
" amount = amount + 1 # 有成绩课程数量增加1\n",
"avg_score = total / amount # 计算平均成绩\n",
"print(avg_score) # 忽略无成绩课程的平均分85.5"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"可以改变判定条件为当前成绩是非空字符串时进行累加,避免使用continue。 \n",
"实际上,python中,大部分使用continue 的情况都可以通过改变条件回避其使用。"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"85.5\n"
]
}
],
"source": [
"score = ['69', '85', '88', '', '100', '76', '', '95']\n",
"total = 0 # 总分初值\n",
"amount = 0 # 有成绩的课程数量初值\n",
"for x in score: # 遍历列表,x每次取值为一个字符串\n",
" if x: # 若当前取值为非空字符串时值为True\n",
" total = total + int(x) # 字符串转整数,并累加到总成绩上\n",
" amount = amount + 1 # 有成绩课程数量增加1\n",
"avg_score = total / amount # 计算平均成绩\n",
"print(avg_score) # 忽略无成绩课程的平均分85.5"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 3.7.3 break 语句 "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"break语句应用于while或for<font color=Red>__循环语句__</font>中,一般置于条件判定语句块中,当满足某条件时触发该语句的执行。\n",
"其作用是在循环次数未达到设定次数或未达到循环终止条件时跳出循环,<font color=Red>__提前结束语句所在层次的循环__</font>。 \n",
"例如枚举时,找到一个满足条件的结果就终止循环。 \n",
"如果一个 for...in 循环被 break 所终结,该循环的控制目标会保持其当前值。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 示例4.10 加法训练机 "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"random模块random.randint(m, n)可以随机产生一个n, m之间的整数,利用这个函数产生两个20以内的正整数a和b,屏幕上输出“a + b = ”,用户计算并输入计算结果,计算机评测计算是否正确。 \n",
"结果正确时输出“恭喜你,回答正确”,回答错误时输出“回答错误,你要加油哦!”。 \n",
"编写一个程序,重复产生两个整数做计算练习,直到用户不再计算,直接输入回车时,输出“练习结束”并结束程序。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"77 + 11 = "
]
},
{
"name": "stdin",
"output_type": "stream",
"text": [
" 12\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"回答错误,你要加油哦!\n",
"30 + 12 = "
]
},
{
"name": "stdin",
"output_type": "stream",
"text": [
" 21\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"回答错误,你要加油哦!\n",
"30 + 9 = "
]
}
],
"source": [
"import random # 导入随机数模块\n",
"\n",
"while True: # 无限循环,每次产生一个新问题\n",
" a = random.randint(1, 150) # 随机产生一个20以内的整数\n",
" b = random.randint(1, 20) # 随机产生一个20以内的整数\n",
" print(F'{a} + {b} = ', end='') # 格式化输出\n",
" result = input() # 用户输入计算结果字符串\n",
" if result == '': # 如果直接输入回车(接收到空字符串)\n",
" print('练习结束')\n",
" break # 结束循环\n",
" elif int(result) == a + b: # 若输入数字等于a+b的值\n",
" print('恭喜你,回答正确') \n",
" else:\n",
" print('回答错误,你要加油哦!')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<font face='楷体' color='red' size=5> 练一练 </font>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"修改示例4.10,使之能够随机产生正整数四则运算的题目进行训练,用户输入计算结果,判断输入正确与否,并统计正确率(只输出算式,未计算的题目不统计在内)。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# 提示,可使用以下方法获得运算符号和转表达式\n",
"sign = random.choice('+-*/') # 随机获取一个运算符号\n",
"eval(f'{a}{sign}{b}') # 可将a、运算符和b组成的字符串转为可运算的表达式求值"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# 补充你的代码\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"测试用例:\n",
"18 / 20 = 0.9\n",
"恭喜你,回答正确\n",
"19 + 10 = 29\n",
"恭喜你,回答正确\n",
"19 * 16 = 361\n",
"回答错误,你要加油哦!\n",
"8 - 8 = 0\n",
"恭喜你,回答正确\n",
"19 - 1 = \n",
"练习结束\n",
"答对3题,正确率为75.0%\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 实例 4.11 自身以外的最大因数"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"输入一个大于1的整数,编程输出其自身以外的最大因数。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"若一个数对i取模的结果为0,则i 是这个数的因数。 \n",
"一个整数的因数可能有很多个,可以用遍历的方法逐一判定。 \n",
"本题要求找最大因数,为提高效率,可以从大到小进行判定,找到的第一个因数时便为最大因数。 \n",
"输出该数后,用break结束循环,不再进行判定。 "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"num = int(input()) # 输入一个整数,例如:100\n",
"for i in range(num - 1, 0, -1): # 遍历小于num且大于1的整数\n",
" if num % i == 0: # 如num可被i整除,则i为num的因数\n",
" print(i) # 输入100时,输出50\n",
" break # 中止循环,退出循环"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<font color=Red>__break只能提前结束当前循环__</font>。 \n",
"当循环层数多于一层时,不能直接用break跳出多重循环。 \n",
"一般的方法可以用一个<font color=Red>__标记变量__</font>,用break退出一重循环后,根据标记变量的值决定是否继续退出外层循环。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 实例 4.12 百钱买百鸡进阶 "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"公鸡五元一只,母鸡三元一只,小鸡三只一元。 \n",
"用户输入想买的鸡的数量和付出的钱数,计算公鸡、母鸡和小鸡的数量。 \n",
"如果有解,输出公鸡最少,小鸡最多的一组;\n",
"如果无解则输出“无解”。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"题目要求如果有解,输出公鸡最少,小鸡最多的一组,可以按公鸡数量由少到多遍历,找到一组解后就结束程序。 \n",
"\n",
"题目需要两层循环,一个break只能结束一层循环,所以可以为内层和外层循环各匹配一个else子句。 \n",
"若内层循环没有遇到break而正常结束,则执行匹配的else(第8行)中的continue(第9行),从而达到跳过内层循环中剩余语句(外层循环中位于第10行的break)的效果。而且因为外层循环未遇到break,会执行与for匹配的else及其输出子句。\n",
"若内层循环遇到break,则会跳过内层循环匹配的else(第8行)及其子句continue,执行张10行的break,这时则会跳过第11行的else及其用于输出的子句。\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"num, money = map(int, (input().split())) # 切分空格分隔的输入转整型\n",
"for cock in range(1, num): # 从小到大遍历公鸡数量\n",
" for hen in range(1, num): # 从小到大遍历母鸡数量\n",
" chicken = num - cock - hen # 小鸡数量计算得到\n",
" if chicken % 3 == 0 and chicken > 0 and 5 * cock + 3 * hen + chicken // 3 == money:\n",
" print(cock, hen, chicken) # 输出找到的第一组解\n",
" break # 结束内层循环\n",
" else: # 如果内层遇到break,跳过else语句:\n",
" continue # 内层未遇到break时执行,跳过当前循环中后续的break语句\n",
" break # 内层遇到break时,执行此语句,结束外层循环并跳过下一个else分支\n",
"else: # 如果外层循环未执行到break,表明无解:\n",
" print('无解')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"else与 continue 及break,所以可以在找到解后设定一个标记,根据标记的值决定是否结束外层循环。 \n",
"也可以根据标记的值是否发生改变判定是否找到了解。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"num, money = map(int, (input().split())) # 切分空格分隔的输入转整型\n",
"flag = False # 设定标记,False为无解,或solution = '无解'\n",
"for cock in range(1, num): # 从小到大遍历公鸡数量\n",
" for hen in range(1, num): # 从小到大遍历母鸡数量\n",
" chicken = num - cock - hen # 小鸡数量计算得到\n",
" if chicken % 3 == 0 and chicken > 0 and 5 * cock + 3 * hen + chicken // 3 == money:\n",
" flag = True # 找到解后改变标记,或solution = '有解' \n",
" print(cock, hen, chicken) # 输出找到的第一组解\n",
" break # 结束内层循环\n",
" if flag: # 根据flag值是否为True判断是否找到解,或if solution == '有解' \n",
" break # 找到解时结束外层循环,否则继续执行外层循环\n",
"if not flag: # 两层循环都结束时,如not flag值为True,表明未找到解,或if solution == '无解'\n",
" print(\"无解\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"程序中有两重循环,在内层循环中找到一个满足条件的解并输出后,按题目要求应该终止程序的执行。 \n",
"提前终止循环可以用break关键字,但该关键字只能终止当前层次的循环,无法终止外层循环的执行。 \n",
"外层循环不能无条件终止,需要先判断是否已经在内层中找到了满足条件的解。 \n",
"所以可以在内层找到解时设定一个标记,上述程序中设置变量flag作为标记,一旦找到了满足条件的解,就改变flag变量的值。 \n",
"在外层循环中根据flag的值是否发生了变化判定是否找到了解,一旦找到了一个满足条件的解,就用break提前终止外层循环。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 3.7.4 else子句 "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Python中的 for...in 和 while 循环都有一个可选的else子句,在<font color=Red>__循环迭代正常完成__</font>之后执行(包括执行0次)。 \n",
"else 子句可以省略,这个子句只有当循环以正常方式结束时,else子句中的语句才能被执行。 \n",
"如果在循环语句块中<font color=Red>__遇到break语句__</font>跳出循环或<font color=Red>__遇到return语句__</font>结束程序,则不会执行else 部分。\n",
"\n",
"在 for 循环中,else 子句会在循环成功结束最后一次迭代之后执行。 \r",
"\r\n",
"在 while 循环中,它会在循环条件变为假值后执行。无论哪种循环,如果因为 break 而结束,那么 else 子句就不会执行。 \r\n",
"else 子句用于循环时比起 if 语句的 else 子句,更像 try 语句的。try 语句的 else 子句在未发生异常时执行,循环的 else 子句则在未发生 break 时执行。 。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 实例 4.13 输出小于n的素数 "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"用户输入一个大于 1 的正整数n,计算并输出小于 n 的素数。 \n",
"素数也称为质数,是指在大于1的自然数中,除了1和它本身以外不再有其他因数的自然数。 \n",
"判定一个整数 n 是否是素数有两个条件: \n",
"一是这个数 n 是<font color=Red>__大于1__</font>的; \n",
"二是这个数 n 不能被从2到n-1中的任意一个数整除,只要<font color=Red>__存在2到n-1之间的因子__</font>,那么n就不是素数。"
]
},
{
"cell_type": "raw",
"metadata": {},
"source": [
"算法描述:\n",
"1. 从n到1逆序遍历:\n",
" a. 判定从 2 到 i-1 之中是否还存在能整除的数:\n",
" ⅰ. 如果存在一个能整除的数字:\n",
" 1. 则数字 i 必然不是素数,不需要继续判断,用break跳出循环\n",
" ⅱ. 如果顺利完成从 2 到 i-1 的遍历,未发现能整除的数,说明该数是素数\n",
" 1. 输出这个数"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"n = int(input()) # 输入一个正整数,例如输入50\n",
"for i in range(2, n): # 0,1不是素数,产生从2 到 n 的整数序列\n",
" for j in range(2, i): # 产生从2到i-1序列,j逐个取值为2到i-1\n",
" if i % j == 0: # 若2到i-1中存在能被i整除的数,i不是素数\n",
" break # 存在整数因子时执行break语句并跳过else语句的执行\n",
" else: # 与for对齐,循环中未执行到break时执行此语句\n",
" print(i, end=' ') # 输出2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"用else语句改写实例 4.12 百钱买百鸡进阶,了解break和continue的使用:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"num, money = map(int, (input().split())) # 切分空格分隔的输入转整型\n",
"flag = False # 设定标记,False为无解,或solution = '无解'\n",
"for cock in range(1, num): # 从小到大遍历公鸡数量\n",
" for hen in range(1, num): # 从小到大遍历母鸡数量\n",
" chicken = num - cock - hen # 小鸡数量计算得到\n",
" if chicken % 3 == 0 and chicken > 0 and 5 * cock + 3 * hen + chicken // 3 == money:\n",
" flag = True # 找到解后改变标记,或solution = '有解'\n",
" print(cock, hen, chicken) # 输出找到的第一组解\n",
" break # 结束内层循环\n",
" if flag: # 内层未遇到break时执行continue\n",
" break\n",
"else: # 外层循环未遇到break时执行缩进语句块\n",
" print(\"无解\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" while…else用法类似于for…else,仅当while<font color=Red>__因条件为假而退出__</font>(即没有被break中断)时运行else分支下的语句块。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 实例 4.14 自除数"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"一个不含0的多位数,如果它能被它的每一位除尽,则它是一个自除数。 \n",
"例如128是一个自除数,因为128能被1、2、8整除。 \n",
"编写函数selfDivisor(num)判断num是否为自除数,使用该函数输出不大于N的所有自除数。 \n",
"(注意,含有数字0的数不是自除数)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"需要注意的是,每次都要从最小的质数开始尝试除,例如360可以除2、除2、除2,被2整除3次才得到一个不能被2整除的45,然后再除3,除3,最后得到质数5。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"num = int(input()) # 输入一个多位正整数\n",
"for c in str(num): # 对数字num中的每位数字进行遍历\n",
" if num % int(c) != 0: # 测试num的每一位是否是num的因子\n",
" print('不是自除数') # 如果存在不能整除的数,则不是自除数\n",
" break # 提前结束循环\n",
"else: # 如果for遍历顺利结束,未遇到break,则执行else子句\n",
" print('是自除数')"
]
},
{
"cell_type": "raw",
"metadata": {},
"source": [
"测试用例:\n",
"128\n",
"是自除数\n",
"129\n",
"不是自除数"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.5"
}
},
"nbformat": 4,
"nbformat_minor": 4
}