🎮 break、continue 与函数——让循环听你指挥!
🎯 上集回顾
先来验收一下咱们的学习成果!
上一集我们玩转了 while 循环,不仅用 while 循环搞定了 1 到 100 的求和,还分别用 while 和 for 循环算出了神秘的水仙花数。更酷的是,我们用无限循环 + 循环嵌套给猜数字游戏来了一次大升级!
💭 上集思考题:用 while 循环双重嵌套打印九九乘法表,你做出来了吗?没做出来的话,看完这篇再回去试试,会有新思路哦!
🚦 break 和 continue——循环的"遥控器"
上集我们学了无限循环(也叫死循环),有人说:"死循环一旦跑起来,就再也停不下来了……"
真的只能这样吗? 当然不是!
没学 break 之前,确实有点束手无策——除了强行关掉程序,或者拔电源(开玩笑的😂)。但掌握了 break 之后,就像拿到了循环的"紧急停止按钮",想停就停!另外还有 return 语句也能终止循环,不过它更多用在函数里,后面会讲到。
break 和 continue 就像循环的遥控器,让你能随心所欲地控制循环的执行流程。
🎬 生活小剧场理解概念
🎫 break 的故事——托尼老弟中彩票了!
托尼老弟在美容美发店上班,每天重复着同样的工作,就像个无限循环。突然有一天,他买的彩票中了 5000万!托尼老弟当场把围裙一扔:"老子再也不用上班啦!"
break 就像那张中奖彩票——一旦触发,立刻跳出循环,再也不用回头!
🤧 continue 的故事——托尼老弟感冒了
托尼老弟还在美容美发店上班(毕竟中彩票是小概率事件😅)。今天气温骤降,他感冒了,只能请一天假。但明天病好了,还得继续上班。
continue 就像这场感冒——跳过今天(本次循环),但明天(下一次循环)还得继续!
搞懂了这个比喻,我们来看看代码怎么写!
💥 break 语句——说停就停!
break 的语法超简单,在需要跳出循环的地方写上就行。它通常和 if 语句搭配,满足某个条件时"啪"的一下就跳出去了!
⚠️ 注意:如果在嵌套循环里用 break,它只会跳出当前所在的那一层循环。
while 循环中的 break:
while 条件表达式1: 执行代码 if 条件表达式2: break # 满足条件,立马跑路!
for 循环中的 break:
for 迭代变量 in 对象: if 条件表达式: break # 满足条件,立马跑路!
🎓 实战案例:托尼老弟的逆袭之路
托尼老弟在美发店打工,每天累得像条狗。我跟他说:"坚持学 Python 三个月,你就能脱离苦海!"
来看看托尼老弟是怎么用 break 跳出"打工循环"的:
study_days = 80 # 已经学了80天 while True: # 无限循环——每天重复的生活 study_days += 1 print(f'💈 美发店上班,晚上坚持学Python 第 {study_days} 天') if study_days > 90: # 学了90天,学成啦! print('🎉 Python 已学成,再也不用去美发店上班啦!') break # 跳出循环,解放啦!💡 代码解读:while True 是个无限循环,代表托尼老弟日复一日的打工生活。当 study_days > 90 时,break 触发,循环结束,托尼老弟成功转型程序员!
⏭️ continue 语句——跳过今天,明天再来!
continue 的语法同样简单。它和 break 的区别在于:break 是彻底退出,continue 只是跳过本次,后面的循环还会继续。
while 循环中的 continue:
while 条件表达式1: 执行代码 if 条件表达式2: continue # 跳过本次循环剩余代码,直接进入下一次
for 循环中的 continue:
for 迭代变量 in 对象: if 条件表达式: continue # 跳过本次循环剩余代码,直接进入下一次
🤒 实战案例:托尼老弟感冒了
托尼老弟学 Python 的第88天,不幸感冒了(可能是熬夜敲代码导致的😂)。今天没法去美发店上班,但明天好了还得继续。
study_days = 80 while True: study_days += 1 if study_days == 88: # 第88天感冒了 print('🤧 老弟今天感冒了,请假一天!') continue # 跳过今天的工作,但循环继续 if study_days > 90: # 学满90天,成功上岸 print('🎉 Python 已学成,再也不用去美发店上班啦!') break print(f'💈 美发店上班,晚上坚持学Python 第 {study_days} 天')
💡 代码解读:当 study_days == 88 时,continue 触发,跳过了当天的打印语句,但循环并没有结束。第89天、90天继续执行,直到 break 触发才退出。
🎯 break vs continue 对比总结
⚠️ 重要提醒:在嵌套循环中,break 和 continue 只作用于它们所在的最内层循环!
🧩 函数——代码的"乐高积木"
乐高积木大家都玩过吧?一块块标准化的组件,通过不同的组合方式,能拼出汽车、城堡、飞船……简直无所不能!
函数就是编程世界的"乐高积木"!
随着你写的代码越来越多,程序会越来越复杂,就像一团乱麻。这时候就需要函数来帮忙了——把重复的代码打包起来,要用的时候直接"召唤",代码瞬间变得清爽又优雅!
还记得上一篇猜数字游戏吗?判断用户输入是否合法的代码出现了两次,简直是在复制粘贴。学了函数,这种重复代码就能一键消灭!
🎁 函数有什么用?
| |
|---|
| |
| 用 calculate_area() 比看一堆公式直观多了 |
| |
| |
📝 使用函数两步走
第1步:定义函数(把代码打包) ↓ 第2步:调用函数(使用打包好的代码)
Python 自带了很多内置函数,比如 print()、max()、min()、len() 等等,开箱即用。当然,我们也可以自己造轮子——自定义函数!
💪 函数是 Python 编程的基石,一定要跟着文档动手敲,光看是学不会的!
✍️ 定义和调用函数
先来看函数的语法结构:
🎪 开胃菜:pass 语句
在正式写函数之前,先认识一下 pass——它是 Python 里的"占位符",表示"这里暂时空着,我先占个位置"。
比如你想写一个求和函数,但还没想好怎么实现,就可以先用 pass 占位,代码不会报错:
def 求和(x, y): pass # 先占个坑,以后再来填
💡 pass 就像你占座时放的书包——表示"这个位置有人了",但人还没来。
🎬 实战:热情的打招呼函数
每次上课都想跟大家说10遍"大家好,想死你们了",手动打印太傻了,让函数来帮忙:
def 打招呼(): # 定义函数 for i in range(10): print('大家好,想死你们了!') 打招呼() # 调用函数 # 🎉 运行结果 大家好,想死你们了! 大家好,想死你们了! 大家好,想死你们了! 大家好,想死你们了! 大家好,想死你们了! 大家好,想死你们了! 大家好,想死你们了! 大家好,想死你们了! 大家好,想死你们了! 大家好,想死你们了!💡 注意:这个函数没有参数,也没有返回值——函数可以很简单,也可以很复杂,根据需求来!
🎁 参数和返回值——函数的"输入输出"
💝 生动理解:女朋友函数
来听一个有趣的故事,帮你理解参数和返回值:
假设你的女朋友是一个函数:
你给她的关心、买的礼物 → 输入参数(参数)
她的反应、回礼 → 返回值(return)
啥都不给 → 参数为空
她不理你 → 返回 None
函数的灵活性:
✅ 可以没有参数(你不送礼物)
✅ 可以有多个参数(口头关心 + 实物礼物)
✅ 可以没有返回值(她默默收下,没反应)
✅ 可以有返回值(她回赠你一个吻)
当函数执行到 return 时,函数立即结束,后面的代码不会执行!
💔 实战代码:女朋友模拟器
def girlfriend(gift=None): """ 女朋友函数 参数:gift - 你送的礼物 返回:女朋友的反应 """ if gift is None: print("😒 啥都不送,还想要我表示?") return None # 没礼物,没好脸色 elif gift == 'LV': return "😘 I LOVE YOU!" # 送LV,收获爱情! elif gift == '多喝热水': print("🙄 滚滚滚!") return None # 直男礼物,凉凉 else: print("😐 就这?") return "谢谢" # 普通礼物,礼貌回应 # 测试各种情况 print("=== 测试1:啥都不送 ===") print(f"结果:{girlfriend()}") print("\n=== 测试2:送LV ===") print(f"结果:{girlfriend('LV')}") print("\n=== 测试3:送'多喝热水' ===") print(f"结果:{girlfriend('多喝热水')}") print("\n=== 测试4:送玫瑰花 ===") print(f"结果:{girlfriend('玫瑰花')}")🎯 运行结果分析:
| | |
|---|
| None | |
'LV' | "I LOVE YOU!" | |
'多喝热水' | None | |
'玫瑰花' | "谢谢" | |
💡 结论:只有送 LV 的时候,女朋友才给了正面反馈。所以兄弟们,懂了吗?😂
🎭 形参 vs 实参——"剧本"与"演员"
来认识两个重要概念:
🎬 实战:计算长方形面积
def rect_area(width, height): # width、height 是形参(剧本角色) area = width * height return area # 调用函数 r_area = rect_area(320, 480) # 320、480 是实参(实际演员) print(f"320 × 480 的长方形面积: {r_area}") # 运行结果 320 × 480 的长方形面积: 153600

💡 记忆口诀:
🔑 关键字参数——"点名道姓"传参数
刚才的形参实参是按位置对应的,必须记住哪个参数在前、哪个在后。如果搞混了顺序,结果就错了!
有没有更优雅的方式? 有!关键字参数——直接"点名道姓"告诉函数:这个值是给哪个参数的!
🎯 实战:关键字参数的魅力
def rect_area(width, height): area = width * height return area # 方式1:传统位置参数 r_area = rect_area(320, 480) # 方式2:关键字参数(顺序可以乱!) r_area = rect_area(width=320, height=480) r_area = rect_area(height=480, width=320) # 顺序反过来也行! print(f"面积: {r_area}") # 结果都一样:153600✨ 关键字参数的优势:
| |
|---|
| rect_area(width=320, height=480) |
| |
| |
💡 建议:参数多的函数,优先使用关键字参数,代码更清晰!
🎁 参数默认值——"保底选项"
有时候,某个参数在大多数情况下都是同一个值,只有少数情况会变化。每次都传一样的参数,太麻烦了!
解决方案:给参数设置默认值!
🎯 实战:默认高度为480的长方形
假设你经常计算各种宽度的长方形面积,但高度基本都是480:
def rect_area(width, height=480): # height有默认值480 area = width * height return area # 情况1:只传宽度,高度用默认值 r_area = rect_area(320) print(f"320 × 480 的面积: {r_area}") # 153600 # 情况2:传两个参数,覆盖默认值 r_area = rect_area(320, 600) print(f"320 × 600 的面积: {r_area}") # 192000 # 情况3:用关键字参数,更清楚 r_area = rect_area(width=320) # 高度用默认480 r_area = rect_area(width=320, height=720) # 高度改成720
💡 恍然大悟:print() 函数的 end 参数
学了默认参数,终于明白 print() 的 end 参数了!
# print() 的完整形式其实是这样的: print(value, ..., end='\n') # end默认是换行符 # 所以默认情况下,每次print都会换行 print("第一行") print("第二行") # 如果改成空格,就不会换行了 print("A", end=' ') print("B", end=' ') print("C") # 输出:A B C🎓 下节预告:关于函数的更多骚操作(可变参数、多返回值),等我们学完元组后再来解锁!
🎮 实战:用函数重构猜数字游戏
学了函数,是时候展示真正的技术了!
还记得上一篇的猜数字游戏吗?那段代码里,判断用户输入是否合法的逻辑出现了两次,简直是复制粘贴的典范:
# 第一次出现 input_string = input("设了个数字,你来猜猜看:") while not input_string.isdigit(): input_string = input("您输入了非数字字符,请输入正确的数字:") else: guess_number = int(input_string) # ... 游戏逻辑 ... # 第二次出现(一模一样的代码!) input_string = input("设了个数字,你来猜猜看:") while not input_string.isdigit(): input_string = input("您输入了非数字字符,请输入正确的数字:") else: guess_number = int(input_string)这种重复代码,就是函数的用武之地!
✨ 重构后的优雅代码:
import random secret_number = random.randint(0, 10) def get_valid_input(): """ 获取用户输入的合法数字 如果输入不是数字,会循环提示直到输入正确 """ input_string = input("设了个数字,你来猜猜看:") while not input_string.isdigit(): input_string = input("❌ 输入错误!请输入正确的数字:") return int(input_string) # 游戏主逻辑 guess_number = get_valid_input() while guess_number != secret_number: if guess_number > secret_number: print("📉 不好意思,您猜大了") else: print("📈 您猜的有点小") guess_number = get_valid_input() # 复用函数! print("🎉 大吉大利,今晚吃鸡!")
🎯 重构的好处:
💡 编程格言:DRY - Don't Repeat Yourself(不要重复你自己)!遇到重复代码,第一反应应该是:能不能写成函数?
📚 内置函数——Python 的"百宝箱"
Python 自带了一大波内置函数,开箱即用,无需导入任何模块!
你已经用过很多内置函数了:print()、input()、len()、range()……这些都是 Python 官方给你准备好的"工具",直接拿来用就行。
🧰 Python3 内置函数大全
| | | | |
|---|
abs() | delattr() | hash() | memoryview() | set() |
all() | dict() | help() | min() | setattr() |
any() | dir() | hex() | next() | slice() |
ascii() | divmod() | id() | object() | sorted() |
bin() | enumerate() | input() | oct() | staticmethod() |
bool() | eval() | isinstance() | open() | str() |
breakpoint() | exec() | issubclass() | pow() | sum() |
bytearray() | filter() | iter() | print() | super() |
bytes() | float() | len() | property() | tuple() |
callable() | format() | list() | range() | type() |
chr() | frozenset() | locals() | repr() | vars() |
classmethod() | getattr() | map() | reversed() | zip() |
compile() | globals() | max() | round() | __import__() |
complex() | hasattr() | | | |
📖 完整文档:Python 官方内置函数文档
🎯 实战:max() 和 min() 函数
这两个函数超级常用,用来找最大/最小值:
# 方式1:直接传多个参数 print(f"max(60, 100, 1000) = {max(60, 100, 1000)}") # 1000 print(f"min(60, 100, 1000) = {min(60, 100, 1000)}") # 60 # 方式2:传一个列表/元组 scores = [85, 92, 78, 96, 88] print(f"最高分: {max(scores)}") # 96 print(f"最低分: {min(scores)}") # 78 # 方式3:结合key参数,更强大 words = ["apple", "banana", "cat"] print(f"最长的单词: {max(words, key=len)}") # banana💡 学习建议:不需要死记硬背所有内置函数,遇到需求时去查文档,常用的用多了自然就记住了!
🧊 元组——"冻住"的列表
前面我们学了列表(list),现在来认识它的"表亲"——元组(tuple)!
它们就像一对性格迥异的兄弟:
列表 = 活泼好动,想改就改
元组 = 沉稳内敛,一旦确定就不变
🎭 元组 vs 列表:一对表亲
👬 相同点(家族基因):
⚡ 不同点(性格差异):
💡 形象记忆:元组就是"冻住"的列表——tuple 谐音 "特厚"(皮厚冻不坏)😂
✍️ 创建元组的两种方式
方式1:小括号直接创建
# 多个元素 t1 = (1, 2, 3, 4, 5) # 混合类型 t2 = ("渣男教父", 33, True, "Python") # 空元组 t3 = ()方式2:tuple() 函数转换
# 从列表转元组 list_data = [1, 2, 3] t4 = tuple(list_data) # (1, 2, 3) # 从字符串转元组 t5 = tuple("Hello") # ('H', 'e', 'l', 'l', 'o') # 从range转元组 t6 = tuple(range(5)) # (0, 1, 2, 3, 4)
⚠️ 超级重点:单元素元组的陷阱!
如果元组只有一个元素,必须加逗号,否则 Python 会认为是普通括号:
# ❌ 错误写法(这不是元组!) t = (100) print(type(t)) # <class 'int'> 变成整数了! # ✅ 正确写法(注意后面的逗号!) t = (100,) print(type(t)) # <class 'tuple'> 这才是元组! # 括号甚至可以省略 t = 100, print(type(t)) # <class 'tuple'>
💡 记忆口诀:单元素元组,逗号是灵魂!

📦 打包和拆包——元组的"魔法"
元组有一个超级实用的特性——打包(packing)和拆包(unpacking)!
这是 Python 中非常优雅的语法糖,让代码简洁又高效。
📦 打包(Packing)
把多个值"包"进一个元组:
# 等号右边有多个值,自动打包成元组 info = "渣男教父", 33, True, "Game、Python" print(info) # ('渣男教父', 33, True, 'Game、Python') print(type(info)) # <class 'tuple'>📤 拆包(Unpacking)
把元组里的值"拆"给多个变量:
bafu_info = ('渣男教父', 33, True, 'Game、Python') # 拆包:左边变量数 = 右边元素数 name, age, married, hobby = bafu_info print(f"姓名: {name}") # 渣男教父 print(f"年龄: {age}") # 33 print(f"已婚: {married}") # True print(f"爱好: {hobby}") # Game、Python
🎯 完整演示:
# 1️⃣ 先打包 bafu_info = ('渣男教父', 33, True, 'Game、Python') print(f"📦 打包结果: {bafu_info}") # 2️⃣ 再拆包 name, age, married, hobby = bafu_info print(f"📤 拆包结果: {name}, {age}, {married}, {hobby}") # 3️⃣ 重新打包(顺序打乱) info = name, hobby, age, married print(f"📦 再打包: {info}") # 输出: # 📦 打包结果: ('渣男教父', 33, True, 'Game、Python') # 📤 拆包结果: 渣男教父, 33, True, Game、Python # 📦 再打包: ('渣男教父', 'Game、Python', 33, True)
💡 核心规则:拆包时,左边变量的数量必须等于右边元素的数量,否则会报错!
🌟 函数可变参数——想传几个传几个!
还记得前面说的元组打包拆包吗?现在它要跟函数联手搞事情了!
场景:你想写一个函数,计算任意个数的数字之和。但问题是——不知道用户会传几个数!
解决方案:*args 可变参数!
🔮 魔法语法:*args
在定义函数时,给参数前面加个 *,它就变成了"可变参数":
def my_sum(*numbers): # * 表示接收任意数量的参数 """计算任意个数数字的和""" total = 0 for n in numbers: total += n return total # 调用时可以传任意个数! print(my_sum(1, 2, 3)) # 6 print(my_sum(10, 20)) # 30 print(my_sum()) # 0 print(my_sum(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)) # 55
💡 原理揭秘:*numbers 会把传入的所有参数打包成一个元组!
🎁 函数的"多返回值"
Python 函数可以一次返回多个值,本质上就是返回一个元组:
def calculate(a, b): """同时返回和、差、积、商""" sum_val = a + b diff_val = a - b prod_val = a * b quot_val = a / b if b != 0 else None return sum_val, diff_val, prod_val, quot_val # 返回4个值! # 拆包接收多个返回值 s, d, p, q = calculate(10, 3) print(f"和: {s}, 差: {d}, 积: {p}, 商: {q:.2f}") # 输出:和: 13, 差: 7, 积: 30, 商: 3.33
🎯 综合实战:奇偶分离器
def separate_odd_even(*numbers): """ 接收任意数量的整数 返回:奇数之和, 偶数之和 """ odd_sum = 0 # 奇数和 even_sum = 0 # 偶数和 for num in numbers: if num % 2 == 0: even_sum += num else: odd_sum += num return odd_sum, even_sum # 返回两个值! # 调用 odd, even = separate_odd_even(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) print(f"奇数之和: {odd}") # 25 print(f"偶数之和: {even}") # 30🎓 下节预告:今天只是函数的入门,后续还会讲函数嵌套、变量作用域、匿名函数(lambda)等高级玩法,敬请期待!
文档总结
一、核心知识点回顾
1. 循环控制语句
| | |
|---|
break | 立即终止 | 当满足某个条件时需要提前结束循环,如找到目标值后停止搜索 |
continue | 跳过本次 | 当满足某个条件时需要跳过当前迭代,如过滤掉某些不符合条件的数据 |
重要提醒:在嵌套循环中,break 和 continue 只作用于它们所在的最内层循环。
2. 函数基础
函数的定义与调用流程:
定义函数(def) → 封装代码块 → 调用函数(函数名()) → 执行代码
函数的组成部分:
参数传递方式:
位置参数:按顺序传递,实参与形参一一对应
关键字参数:通过 参数名=值 的方式传递,可以打乱顺序
默认参数:在定义时给参数指定默认值,调用时可省略
可变参数:使用 *args 接收任意数量的位置参数,自动打包成元组
3. 元组(tuple)
元组与列表的对比:
| | |
|---|
| [元素1, 元素2] | (元素1, 元素2) |
| 可变 | 不可变 |
| | |
| | |
打包与拆包:
4. 内置函数
Python 提供了丰富的内置函数,本文档重点介绍了 max() 和 min(),它们可以:
接收多个独立参数:max(1, 5, 3) → 返回 5
接收一个可迭代对象:max([1, 5, 3]) → 返回 5
二、学习建议
函数是代码复用的核心:遇到重复代码时,第一时间考虑是否可以封装成函数
参数设计要灵活:合理使用默认参数和可变参数,让函数更通用
理解不可变性的意义:元组的不可变性使其成为字典的键、集合的元素,也保证了数据安全
多练习打包拆包:这是 Python 中非常优雅的特性,熟练掌握可以让代码更简洁
三、下篇预告
下一篇我们将学习 Python 中另外两种重要的数据结构——字典(dict)和集合(set),以及面向对象编程的基础——类与对象。字典是键值对的集合,非常适合表示有映射关系的数据;集合则用于存储不重复的元素,常用于去重和集合运算。
🎮 动手练一练
光看不练假把式!下面几道题目帮你巩固今天学到的知识,建议先自己思考,再看参考答案。
选择题
1. 以下关于 break 语句的描述,正确的是?
A. 用于跳出当前循环
B. 用于跳过当前循环的剩余语句
C. 用于结束整个程序
D. 用于定义函数
💡 答案解析(点击展开)
正确答案:A
详细解析:
break 语句的作用是立即终止它所在的那一层循环,程序会跳出循环体,继续执行循环后面的代码。
选项 B 描述的是 continue 的功能,continue 是跳过本次循环剩余代码,继续下一次循环。
选项 C 错误,结束整个程序应该使用 exit() 或 quit()(不推荐在生产环境使用)。
选项 D 错误,定义函数使用 def 关键字。
记忆技巧:break 有"打破、中断"的意思,想象你正在循环里跑步,break 就是突然喊停,直接退出跑道。
</details>
2. 以下关于 continue 语句的描述,正确的是?
A. 用于跳出当前循环
B. 用于跳过当前循环的剩余语句,继续下一次循环
C. 用于结束整个程序
D. 用于定义函数
💡 答案解析(点击展开)
正确答案:B
详细解析:
生活类比:
代码示例加深理解:
for i in range(5): if i == 2: continue # 跳过 i=2 的打印 print(i) # 输出:0 1 3 4(注意没有 2)
</details>
3. 以下关于函数的描述,错误的是?
A. 函数可以减少代码重复
B. 函数可以提高代码可读性
C. 函数必须有返回值
D. 函数可以有多个参数
💡 答案解析(点击展开)
正确答案:C
详细解析:
选项 A 正确:将重复代码封装成函数,需要时直接调用,避免复制粘贴。
选项 B 正确:用有意义的函数名将一段逻辑封装起来,代码更易读。比如 calculate_area() 比一堆计算公式直观。
选项 C 错误:函数可以没有返回值!没有 return 语句的函数,或者只有 return 没有返回值的函数,默认返回 None。
def say_hello(): print("Hello!") # 没有 return 语句 result = say_hello() # 输出:Hello! print(result) # 输出:None选项 D 正确:Python 函数支持任意数量的参数,包括位置参数、关键字参数、可变参数等。
常见误区:很多初学者认为函数一定要有 return,其实像 print() 这种执行操作但不需要返回结果的函数也很常见。
</details>
编程题
1. 编写一个函数,判断一个数是否为素数(质数)。
💡 提示:素数是指大于1的自然数,除了1和它本身外,不能被其他自然数整除。
🔑 参考答案与解析(点击展开)
解题思路:
边界处理:小于2的数都不是素数
优化算法:不需要从2检查到n-1,只需要检查到 √n 即可。因为如果 n 有因子大于 √n,那它必然对应一个小于 √n 的因子。
遍历检查:用循环检查2到√n之间是否存在能整除n的数
代码实现:
def is_prime(n): """判断是否为素数 参数: n: 待判断的整数 返回: bool: True表示是素数,False表示不是素数 """ # 边界条件:小于2的数不是素数 if n < 2: return False # 2是素数,但偶数都不是素数(除了2) if n == 2: return True if n % 2 == 0: return False # 只需要检查到平方根,且跳过偶数 for i in range(3, int(n**0.5) + 1, 2): if n % i == 0: return False return True # 测试用例 print(is_prime(17)) # True,17是素数 print(is_prime(18)) # False,18 = 2 × 9 print(is_prime(2)) # True,2是最小的素数 print(is_prime(1)) # False,1不是素数 print(is_prime(97)) # True,97是素数
进一步优化:上面的代码已经做了优化(跳过偶数),如果n很大,这个算法效率会高很多。
时间复杂度:O(√n),比朴素的 O(n) 算法高效得多。
</details>
2. 编写一个函数,计算斐波那契数列的前n项。
💡 提示:斐波那契数列是 0, 1, 1, 2, 3, 5, 8, 13...,从第三项开始,每一项都是前两项之和。
🔑 参考答案与解析(点击展开)
解题思路:
理解数列规律:F(0)=0, F(1)=1, F(n)=F(n-1)+F(n-2)
处理边界情况:n<=0 返回空列表,n==1 返回 [0]
迭代计算:从第3项开始,每一项等于前两项之和
代码实现:
def fibonacci(n): """返回斐波那契数列前n项 参数: n: 要计算的项数 返回: list: 包含前n项斐波那契数的列表 """ # 处理边界情况 if n <= 0: return [] elif n == 1: return [0] elif n == 2: return [0, 1] # 初始化前两项 fib = [0, 1] # 从第3项开始计算,每一项等于前两项之和 for i in range(2, n): next_num = fib[i-1] + fib[i-2] fib.append(next_num) return fib # 测试用例 print(fibonacci(0)) # [] print(fibonacci(1)) # [0] print(fibonacci(2)) # [0, 1] print(fibonacci(10)) # [0, 1, 1, 2, 3, 5, 8, 13, 21, 34] print(fibonacci(20)) # 前20项 # 进阶:只返回第n项(不保存整个列表) def fibonacci_nth(n): """只返回第n项斐波那契数,空间复杂度 O(1)""" if n <= 0: return None elif n == 1: return 0 elif n == 2: return 1 a, b = 0, 1 for _ in range(2, n): a, b = b, a + b # 同时赋值,Pythonic的写法 return b print(f"第20项是: {fibonacci_nth(20)}") # 4181知识点延伸:
上面的 a, b = b, a + b 是 Python 特有的同步赋值,先计算右边所有值,再赋给左边。
如果只关心第n项的值,可以用优化版本,只保存前两个数,空间复杂度从 O(n) 降到 O(1)。
</details>
3. 编写一个函数,接收任意数量的整数,返回其中的最大值和最小值。
💡 提示:需要使用可变参数 *args,并且函数要有两个返回值。
🔑 参考答案与解析(点击展开)
解题思路:
使用可变参数 *args:这样函数可以接受任意数量的参数,如 find_max_min(1, 5, 3) 或 find_max_min()
处理空参数情况:如果没有传入任何参数,应该返回什么?这里返回 (None, None)
利用内置函数:Python 已经提供了 max() 和 min(),直接复用即可
多返回值:Python 函数返回多个值时,实际上是返回一个元组,可以用拆包语法接收
代码实现:
def find_max_min(*numbers): """接收任意数量的整数,返回最大值和最小值 参数: *numbers: 可变数量的整数参数 返回: tuple: (最大值, 最小值),如果没有参数返回 (None, None) """ # 检查是否有参数传入 if not numbers: print("警告:没有传入任何参数!") return None, None # 使用内置函数计算最大最小值 return max(numbers), min(numbers) # 测试用例 # 1. 正常情况 max_val, min_val = find_max_min(3, 1, 4, 1, 5, 9, 2, 6) print(f"最大值: {max_val}, 最小值: {min_val}") # 最大值: 9, 最小值: 1 # 2. 只有一个数 max_val, min_val = find_max_min(42) print(f"最大值: {max_val}, 最小值: {min_val}") # 最大值: 42, 最小值: 42 # 3. 没有参数 max_val, min_val = find_max_min() print(f"最大值: {max_val}, 最小值: {min_val}") # 最大值: None, 最小值: None # 4. 传入列表(需要解包) data = [23, 56, 12, 89, 34] max_val, min_val = find_max_min(*data) # 注意这里的 * 是解包操作 print(f"列表中的最大值: {max_val}, 最小值: {min_val}") # 最大值: 89, 最小值: 12重要知识点:
*numbers 在定义函数时:表示接收任意数量的位置参数,内部是一个元组
*data 在调用函数时:表示解包,将列表/元组的元素逐个作为参数传入
手动实现版本(不使用内置函数):
def find_max_min_manual(*numbers): """手动实现最大最小值查找""" if not numbers: return None, None max_val = min_val = numbers[0] # 初始化为第一个数 for num in numbers[1:]: if num > max_val: max_val = num if num < min_val: min_val = num return max_val, min_val
</details>
4. 使用 break 和 continue 实现:打印1-100之间能被3整除但不能被5整除的数。
💡 提示:需要同时满足两个条件:能被3整除,且不能被5整除。
🔑 参考答案与解析(点击展开)
解题思路:
遍历范围:使用 range(1, 101) 生成1到100的数字
第一个条件:num % 3 != 0 表示不能被3整除,用 continue 跳过
第二个条件:num % 5 == 0 表示能被5整除,也用 continue 跳过
输出结果:通过两个条件的数,打印出来
代码实现:
print("1-100之间能被3整除但不能被5整除的数:") count = 0 # 计数器,统计有多少个符合条件的数 for num in range(1, 101): # 条件1:不能被3整除,跳过 if num % 3 != 0: continue # 条件2:能被5整除,跳过(因为要求"不能被5整除") if num % 5 == 0: continue # 通过筛选,打印该数 print(num, end=' ') count += 1 # 每行打印10个数,方便阅读 if count % 10 == 0: print() # 换行 print(f"\n\n符合条件的数共有 {count} 个") # 输出结果: # 3 6 9 12 18 21 24 27 33 36 # 39 42 48 51 54 57 63 66 69 72 # 78 81 84 87 93 96 99 # # 符合条件的数共有 27 个另一种写法(使用逻辑与):
print("\n使用逻辑与的写法:") for num in range(1, 101): # 同时满足:能被3整除 且 不能被5整除 if num % 3 == 0 and num % 5 != 0: print(num, end=' ')两种写法对比:
数学原理:
能被3整除的数:3, 6, 9, 12, 15, 18, 21, 24, 27, 30...
其中能被5整除的(即能被15整除的):15, 30, 45, 60, 75, 90
所以符合条件的数有:100÷3 ≈ 33个,减去6个能被15整除的,约27个
</details>